Browse Source

always poll for client POLLHUP/POLLERR events (fixes #399)

to detect client disconnect.  Do so even when waiting on backend,
and not polling for POLLRD or POLLWR on client connection.

This reduces unnecessary load on backends when backends are slow
to respond and client has given up waiting.

x-ref:
  "https://redmine.lighttpd.net/issues/399"
  FastCGI performance on high load
personal/stbuehler/mod-csrf-old
Glenn Strauss 6 years ago
parent
commit
4b0c822ed0
  1. 5
      src/connections.c
  2. 29
      src/fdevent.c
  3. 4
      src/fdevent.h
  4. 3
      src/mod_fastcgi.c
  5. 6
      src/mod_proxy.c
  6. 3
      src/mod_scgi.c
  7. 4
      src/server.c

5
src/connections.c

@ -143,6 +143,7 @@ static int connection_close(server *srv, connection *con) {
"(warning) close:", con->fd, strerror(errno));
}
#endif
con->fd = -1;
srv->cur_fds--;
#if 0
@ -1377,11 +1378,11 @@ int connection_state_machine(server *srv, connection *con) {
(con->traffic_limit_reached == 0)) {
fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
} else {
fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, 0);
}
break;
default:
fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, 0);
break;
}

29
src/fdevent.c

@ -150,28 +150,25 @@ int fdevent_unregister(fdevents *ev, int fd) {
return 0;
}
int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
int fde = fde_ndx ? *fde_ndx : -1;
void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
if (-1 == fd) return;
if (NULL == ev->fdarray[fd]) return;
if (NULL == ev->fdarray[fd]) return 0;
if (ev->event_del) fde = ev->event_del(ev, fde, fd);
if (ev->event_del) *fde_ndx = ev->event_del(ev, *fde_ndx, fd);
ev->fdarray[fd]->events = 0;
if (fde_ndx) *fde_ndx = fde;
return 0;
}
int fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
int fde = fde_ndx ? *fde_ndx : -1;
void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
if (-1 == fd) return;
if (ev->event_set) fde = ev->event_set(ev, fde, fd, events);
ev->fdarray[fd]->events = events;
if (fde_ndx) *fde_ndx = fde;
/*(Note: skips registering with kernel if initial events is 0,
* so caller should pass non-zero events for initial registration.
* If never registered due to never being called with non-zero events,
* then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
if (ev->fdarray[fd]->events == events) return;/*(no change; nothing to do)*/
return 0;
if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
ev->fdarray[fd]->events = events;
}
int fdevent_poll(fdevents *ev, int timeout_ms) {

4
src/fdevent.h

@ -173,8 +173,8 @@ fdevents *fdevent_init(struct server *srv, size_t maxfds, fdevent_handler_t type
int fdevent_reset(fdevents *ev); /* "init" after fork() */
void fdevent_free(fdevents *ev);
int fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events); /* events can be FDEVENT_IN, FDEVENT_OUT or FDEVENT_IN | FDEVENT_OUT */
int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd);
void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events); /* events can be FDEVENT_IN, FDEVENT_OUT or FDEVENT_IN | FDEVENT_OUT */
void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd);
int fdevent_event_get_revent(fdevents *ev, size_t ndx);
int fdevent_event_get_fd(fdevents *ev, size_t ndx);
fdevent_handler fdevent_get_handler(fdevents *ev, int fd);

3
src/mod_fastcgi.c

@ -2971,13 +2971,10 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
}
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
/* we don't need the out event anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
fcgi_set_state(srv, hctx, FCGI_STATE_READ);
} else {
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
}
return HANDLER_WAIT_FOR_EVENT;

6
src/mod_proxy.c

@ -819,8 +819,6 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) {
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
proxy_set_state(srv, hctx, PROXY_STATE_READ);
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
} else {
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
@ -967,10 +965,6 @@ static handler_t proxy_handle_fdevent(server *srv, void *ctx, int revents) {
int socket_error;
socklen_t socket_error_len = sizeof(socket_error);
/* we don't need it anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
hctx->fde_ndx = -1;
/* try to finish the connect() */
if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
log_error_write(srv, __FILE__, __LINE__, "ss",

3
src/mod_scgi.c

@ -2352,13 +2352,10 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) {
}
if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
/* we don't need the out event anymore */
fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
scgi_set_state(srv, hctx, FCGI_STATE_READ);
} else {
fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
}
return HANDLER_WAIT_FOR_EVENT;

4
src/server.c

@ -1529,7 +1529,6 @@ int main (int argc, char **argv) {
for (i = 0; i < srv->srv_sockets.used; i++) {
server_socket *srv_socket = srv->srv_sockets.ptr[i];
fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
if (graceful_shutdown) {
/* we don't want this socket anymore,
@ -1538,11 +1537,14 @@ int main (int argc, char **argv) {
* the next lighttpd to take over (graceful restart)
* */
fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
fdevent_unregister(srv->ev, srv_socket->fd);
close(srv_socket->fd);
srv_socket->fd = -1;
/* network_close() will cleanup after us */
} else {
fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, 0);
}
}

Loading…
Cancel
Save