summaryrefslogtreecommitdiff
path: root/src/network.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-01-24 11:29:10 -0500
committerGlenn Strauss <gstrauss@gluelogic.com>2017-01-31 14:40:05 -0500
commit6c1e6e660e97318ed10360002130f03ffbc4a6ae (patch)
tree7dfedd52089aec870aa9e286a11111af3b3d9774 /src/network.c
parentb0c66266d91d60370ebb31c63adab9ca9b8d9aed (diff)
downloadlighttpd1.4-6c1e6e660e97318ed10360002130f03ffbc4a6ae.tar.gz
lighttpd1.4-6c1e6e660e97318ed10360002130f03ffbc4a6ae.zip
[core] graceful restart with SIGUSR1 (fixes #2785)
more consistent cleanup of resources at shutdown (e.g. upon error conditions) Notes: graceful restart with SIGUSR1 - not available if chroot()ed, oneshot mode, or if idle timeout occurs - preserve process id (pid) - preserve existing listen sockets - i.e. does not close old listen sockets from prior configs (even if old listen sockets no longer in the new config) (sockets may have been bound w/ root privileges no longer available) - will fail to add listen sockets from new config if privileges lighttpd configured to drop privileges to non-root user, and new listen socket attempts to bind to low-numbered port requiring root privileges. - will fail if listen sockets in new config conflict with any previous old listen sockets - These failure modes will result in lighttpd shutting down instead of graceful restart. These failure modes are not detectable with preflight checks ('lighttpd -tt -f lighttpd.conf') because the new instance of lighttpd running the preflight check does not known config state of n prior graceful restarts, or even the config state of the currently running lighttpd server. - due to lighttpd feature of optionally managing backends (e.g. fastcgi and scgi via "bin-path"), lighttpd must wait for all child processes to exit prior to restarting. Restarting new workers while old workers (and old backends) were still running would result in failure of restarted lighttpd process to be able to bind to sockets already in use by old backends (e.g. unix "socket" path) x-ref: "graceful restart with SIGUSR1" https://redmine.lighttpd.net/issues/2785
Diffstat (limited to 'src/network.c')
-rw-r--r--src/network.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/src/network.c b/src/network.c
index 2c787d0c..47c00561 100644
--- a/src/network.c
+++ b/src/network.c
@@ -437,12 +437,7 @@ srv_sockets_append:
error_free_socket:
if (srv_socket->fd != -1) {
- /* check if server fd are already registered */
- if (srv_socket->fde_ndx != -1) {
- fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
- fdevent_unregister(srv->ev, srv_socket->fd);
- }
-
+ network_unregister_sock(srv, srv_socket);
close(srv_socket->fd);
}
buffer_free(srv_socket->srv_token);
@@ -457,14 +452,8 @@ int network_close(server *srv) {
size_t i;
for (i = 0; i < srv->srv_sockets.used; i++) {
server_socket *srv_socket = srv->srv_sockets.ptr[i];
-
if (srv_socket->fd != -1) {
- /* check if server fd are already registered */
- if (srv_socket->fde_ndx != -1) {
- fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
- fdevent_unregister(srv->ev, srv_socket->fd);
- }
-
+ network_unregister_sock(srv, srv_socket);
close(srv_socket->fd);
}
@@ -474,6 +463,9 @@ int network_close(server *srv) {
}
free(srv->srv_sockets.ptr);
+ srv->srv_sockets.ptr = NULL;
+ srv->srv_sockets.used = 0;
+ srv->srv_sockets.size = 0;
return 0;
}
@@ -520,9 +512,17 @@ int network_init(server *srv) {
buffer_append_string_len(b, CONST_STR_LEN(":"));
buffer_append_int(b, srv->srvconf.port);
- if (0 != network_server_init(srv, b, 0)) {
- buffer_free(b);
- return -1;
+ /* check if we already know this socket, and if yes, don't init it */
+ for (j = 0; j < srv->srv_sockets.used; j++) {
+ if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, b)) {
+ break;
+ }
+ }
+ if (j == srv->srv_sockets.used) {
+ if (0 != network_server_init(srv, b, 0)) {
+ buffer_free(b);
+ return -1;
+ }
}
buffer_free(b);
@@ -592,6 +592,12 @@ int network_init(server *srv) {
return 0;
}
+void network_unregister_sock(server *srv, server_socket *srv_socket) {
+ if (-1 == srv_socket->fd || -1 == srv_socket->fde_ndx) return;
+ fdevent_event_del(srv->ev, &srv_socket->fde_ndx, srv_socket->fd);
+ fdevent_unregister(srv->ev, srv_socket->fd);
+}
+
int network_register_fdevents(server *srv) {
size_t i;