summaryrefslogtreecommitdiff
path: root/src/mod_dirlisting.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-03-26 22:56:46 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-04-02 01:16:42 -0400
commit8d4da3392c14a3cd171537a37c096570f2143744 (patch)
treeeb5392605d7bf3ffb2361728031f27b065f994b1 /src/mod_dirlisting.c
parent376aea03205920b8b82081a80e6e751279a4d8f6 (diff)
downloadlighttpd-git-8d4da3392c14a3cd171537a37c096570f2143744.tar.gz
[mod_dirlisting] read dir in pieces; less blocking
read dir in pieces, allowing server to do other work between reads (avoid potentially blocking other requests for long periods of time while reading a large directory)
Diffstat (limited to 'src/mod_dirlisting.c')
-rw-r--r--src/mod_dirlisting.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c
index 8becfc7d..626da4dd 100644
--- a/src/mod_dirlisting.c
+++ b/src/mod_dirlisting.c
@@ -16,6 +16,7 @@
#include "base.h"
#include "log.h"
#include "buffer.h"
+#include "connections.h"/* joblist_append() */
#include "fdevent.h"
#include "http_chunk.h"
#include "http_header.h"
@@ -102,6 +103,8 @@ typedef struct {
plugin_config conf;
} handler_ctx;
+#define DIRLIST_BATCH 32
+
static handler_ctx * mod_dirlisting_handler_ctx_init (plugin_data * const p) {
handler_ctx *hctx = calloc(1, sizeof(*hctx));
@@ -916,7 +919,8 @@ static int http_read_directory(handler_ctx * const p) {
const int hide_dotfiles = p->conf.hide_dot_files;
const uint32_t name_max = p->name_max;
struct stat st;
- while ((dent = readdir(p->dp)) != NULL) {
+ int count = -1;
+ while (++count < DIRLIST_BATCH && (dent = readdir(p->dp)) != NULL) {
const char * const d_name = dent->d_name;
const uint32_t dsz = (uint32_t) _D_EXACT_NAMLEN(dent);
if (d_name[0] == '.') {
@@ -978,6 +982,8 @@ static int http_read_directory(handler_ctx * const p) {
tmp->namelen = dsz;
memcpy(DIRLIST_ENT_NAME(tmp), d_name, dsz + 1);
}
+ if (count == DIRLIST_BATCH)
+ return HANDLER_WAIT_FOR_EVENT;
closedir(p->dp);
p->dp = NULL;
@@ -994,10 +1000,6 @@ static void http_list_directory(request_st * const r, handler_ctx * const hctx)
char sizebuf[sizeof("999.9K")];
struct tm tm;
- /* Note: a very large directory may cause lighttpd to pause handling other
- * requests while lighttpd processes directory, especially if directory is
- * on a remote filesystem */
-
/* generate large directory listings into tempfiles
* (estimate approx 200-256 bytes of HTML per item; could be up to ~512) */
chunkqueue * const cq = &r->write_queue;
@@ -1174,6 +1176,9 @@ SUBREQUEST_FUNC(mod_dirlisting_subrequest) {
mod_dirlisting_response(r, hctx);
mod_dirlisting_reset(r, p); /*(release resources, including hctx)*/
break;
+ case HANDLER_WAIT_FOR_EVENT: /*(used here to mean 'yield')*/
+ joblist_append(r->con);
+ break;
default:
break;
}