Project

General

Profile

Bug #760 » bug760.patch

Patch to work around problem of crashing on large files -- geoff - Anonymous, 2007-06-26 22:39

View differences:

chunk.c 2007-05-24 18:13:08.000000000 -0600
return len;
}
off_t chunkqueue_memory_used(chunkqueue *cq) {
off_t used = 0;
chunk *c;
for (c = cq->first; c; c = c->next) {
used += sizeof *c;
switch (c->type) {
case MEM_CHUNK:
used += c->mem->used;
break;
case FILE_CHUNK:
break;
default:
break;
}
}
return used;
}
off_t chunkqueue_written(chunkqueue *cq) {
off_t len = 0;
chunk *c;
chunk.h 2007-05-24 18:13:08.000000000 -0600
int chunkqueue_remove_finished_chunks(chunkqueue *cq);
off_t chunkqueue_length(chunkqueue *c);
off_t chunkqueue_memory_used(chunkqueue *c);
off_t chunkqueue_written(chunkqueue *c);
void chunkqueue_free(chunkqueue *c);
void chunkqueue_reset(chunkqueue *c);
mod_fastcgi.c 2007-05-24 18:19:13.000000000 -0600
FCGI_STATE_CONNECT_DELAYED,
FCGI_STATE_PREPARE_WRITE,
FCGI_STATE_WRITE,
FCGI_STATE_WRITE_QUEUE_FULL,
FCGI_STATE_READ
} fcgi_connection_state_t;
/*
* Limit on how large any write queue is allowed to grow. If the
* queue becomes larger than this, lighttpd will temporarily remove
* the *input* side fd from the event handler until the queue length
* drops. Because of the hacky way in which this feature is
* implemented, the reduced queue length won't be noticed for up to
* one second. For that reason, the queue length should be large
* enough to sustain 2-3 seconds of output across the server's
* connection. On a 100 Mbps Ethernet, that works out to about 25 MB.
* Note that a machine that serves many connections might still run
* out of memory (for example, if MAX_WRITE_QUEUE_SIZE is 32 MB, 100
* connections will expect the server to allocate 3.2 GB, which most
* systems can't handle).
*
* The correct way to implement this feature is to have
* MAX_WRITE_QUEUE_SIZE fairly small, probably around 1 MB, but have
* the wakeup done by chunk.c when the chunk queue drains
* appropriately. That requires more extensive changes, and I'm
* trying to limit the amount of code I change, so I'll leave that
* improvement to someone more familiar with lighttpd. Geoff
* Kuenning, 5/24/2007.
*/
#define MAX_WRITE_QUEUE_SIZE (1 << 25) /* 32 MB */
typedef struct {
fcgi_proc *proc;
fcgi_extension_host *host;
......
fcgi_extension_host *host= hctx->host;
fcgi_proc *proc = hctx->proc;
/*
* Before reading, find out if the write queue is overfull.
* If so, suspend reading. Geoff Kuenning, 5/24/2007.
*/
if (chunkqueue_memory_used(con->write_queue) >= MAX_WRITE_QUEUE_SIZE) {
fdevent_event_del(srv->ev, &(hctx->fde_ndx), fcgi_fd);
fcgi_set_state(srv, hctx, FCGI_STATE_WRITE_QUEUE_FULL);
return 0;
}
/*
* check how much we have to read
*/
......
case FCGI_STATE_READ:
/* waiting for a response */
break;
case FCGI_STATE_WRITE_QUEUE_FULL:
/*
* We stopped reading because the write queue is full.
* See if we can read again. If so, put the fd back
* in the event list. Geoff Kuenning, 5/24/2007.
*/
if (chunkqueue_memory_used(con->write_queue) < MAX_WRITE_QUEUE_SIZE) {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
fcgi_set_state(srv, hctx, FCGI_STATE_READ);
}
break;
default:
log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
return HANDLER_ERROR;
......
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
break;
case FCGI_STATE_WRITE_QUEUE_FULL:
/*
* We stopped reading because the write queue
* is full. See if we can read again. If so,
* put the fd back in the event list. Geoff
* Kuenning, 5/24/2007.
*/
if (chunkqueue_memory_used(con->write_queue) < MAX_WRITE_QUEUE_SIZE) {
fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
fcgi_set_state(srv, hctx, FCGI_STATE_READ);
}
break;
case FCGI_STATE_INIT:
/* at reconnect */
break;
(4-4/4)