version 1.16, 2014/01/02 08:21:38 |
version 1.16.4.3, 2019/06/15 15:54:58 |
|
|
/* $eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $ */ |
/* $eterna: daemon-bozo.c,v 1.24 2011/11/18 09:21:15 mrg Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1997-2014 Matthew R. Green |
* Copyright (c) 1997-2019 Matthew R. Green |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
Line 70 static pid_t pidfile_pid = 0; |
|
Line 70 static pid_t pidfile_pid = 0; |
|
static void |
static void |
sigchild(int signo) |
sigchild(int signo) |
{ |
{ |
while (waitpid(-1, NULL, WNOHANG) > 0) { |
|
} |
while (waitpid(-1, NULL, WNOHANG) > 0) |
|
/* nothing */; |
} |
} |
|
|
/* Signal handler to exit in a controlled manner. This ensures that |
/* Signal handler to exit in a controlled manner. This ensures that |
Line 105 create_pidfile(bozohttpd_t *httpd) |
|
Line 106 create_pidfile(bozohttpd_t *httpd) |
|
return; |
return; |
|
|
if (atexit(remove_pidfile) == -1) |
if (atexit(remove_pidfile) == -1) |
bozo_err(httpd, 1, "Failed to install pidfile handler"); |
bozoerr(httpd, 1, "Failed to install pidfile handler"); |
|
|
if ((file = fopen(httpd->pidfile, "w")) == NULL) |
if ((file = fopen(httpd->pidfile, "w")) == NULL) |
bozo_err(httpd, 1, "Failed to create pidfile '%s'", |
bozoerr(httpd, 1, "Failed to create pidfile '%s'", |
httpd->pidfile); |
httpd->pidfile); |
(void)fprintf(file, "%d\n", getpid()); |
(void)fprintf(file, "%d\n", getpid()); |
(void)fclose(file); |
(void)fclose(file); |
Line 138 bozo_daemon_init(bozohttpd_t *httpd) |
|
Line 139 bozo_daemon_init(bozohttpd_t *httpd) |
|
h.ai_flags = AI_PASSIVE; |
h.ai_flags = AI_PASSIVE; |
e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0); |
e = getaddrinfo(httpd->bindaddress, portnum, &h, &r0); |
if (e) |
if (e) |
bozo_err(httpd, 1, "getaddrinfo([%s]:%s): %s", |
bozoerr(httpd, 1, "getaddrinfo([%s]:%s): %s", |
httpd->bindaddress ? httpd->bindaddress : "*", |
httpd->bindaddress ? httpd->bindaddress : "*", |
portnum, gai_strerror(e)); |
portnum, gai_strerror(e)); |
for (r = r0; r != NULL; r = r->ai_next) |
for (r = r0; r != NULL; r = r->ai_next) |
Line 151 bozo_daemon_init(bozohttpd_t *httpd) |
|
Line 152 bozo_daemon_init(bozohttpd_t *httpd) |
|
continue; |
continue; |
if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on, |
if (setsockopt(httpd->sock[i], SOL_SOCKET, SO_REUSEADDR, &on, |
sizeof(on)) == -1) |
sizeof(on)) == -1) |
bozo_warn(httpd, "setsockopt SO_REUSEADDR: %s", |
bozowarn(httpd, "setsockopt SO_REUSEADDR: %s", |
strerror(errno)); |
strerror(errno)); |
if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1) |
if (bind(httpd->sock[i], r->ai_addr, r->ai_addrlen) == -1) |
continue; |
continue; |
Line 163 bozo_daemon_init(bozohttpd_t *httpd) |
|
Line 164 bozo_daemon_init(bozohttpd_t *httpd) |
|
i++; |
i++; |
} |
} |
if (i == 0) |
if (i == 0) |
bozo_err(httpd, 1, "could not find any addresses to bind"); |
bozoerr(httpd, 1, "could not find any addresses to bind"); |
httpd->nsock = i; |
httpd->nsock = i; |
freeaddrinfo(r0); |
freeaddrinfo(r0); |
|
|
Line 172 bozo_daemon_init(bozohttpd_t *httpd) |
|
Line 173 bozo_daemon_init(bozohttpd_t *httpd) |
|
|
|
create_pidfile(httpd); |
create_pidfile(httpd); |
|
|
bozo_warn(httpd, "started in daemon mode as `%s' port `%s' root `%s'", |
bozowarn(httpd, "started in daemon mode as `%s' port `%s' root `%s'", |
httpd->virthostname, portnum, httpd->slashdir); |
httpd->virthostname, portnum, httpd->slashdir); |
|
|
signal(SIGHUP, controlled_exit); |
signal(SIGHUP, controlled_exit); |
Line 204 daemon_runchild(bozohttpd_t *httpd, int |
|
Line 205 daemon_runchild(bozohttpd_t *httpd, int |
|
} |
} |
|
|
static int |
static int |
daemon_poll_err(bozohttpd_t *httpd, int fd, int idx) |
daemon_poll_err(bozohttpd_t *httpd, int idx) |
{ |
{ |
if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0) |
if ((httpd->fds[idx].revents & (POLLNVAL|POLLERR|POLLHUP)) == 0) |
return 0; |
return 0; |
|
|
bozo_warn(httpd, "poll on fd %d pid %d revents %d: %s", |
bozowarn(httpd, "poll on fd %d pid %d revents %d: %s", |
httpd->fds[idx].fd, getpid(), httpd->fds[idx].revents, |
httpd->fds[idx].fd, getpid(), httpd->fds[idx].revents, |
strerror(errno)); |
strerror(errno)); |
bozo_warn(httpd, "nsock = %d", httpd->nsock); |
bozowarn(httpd, "nsock = %d", httpd->nsock); |
close(httpd->sock[idx]); |
close(httpd->sock[idx]); |
httpd->nsock--; |
httpd->nsock--; |
bozo_warn(httpd, "nsock now = %d", httpd->nsock); |
bozowarn(httpd, "nsock now = %d", httpd->nsock); |
/* no sockets left */ |
/* no sockets left */ |
if (httpd->nsock == 0) |
if (httpd->nsock == 0) |
exit(0); |
exit(0); |
|
|
/* fail on programmer errors */ |
/* fail on programmer errors */ |
if (errno == EFAULT || |
if (errno == EFAULT || |
errno == EINVAL) |
errno == EINVAL) |
bozo_err(httpd, 1, "poll: %s", |
bozoerr(httpd, 1, "poll: %s", |
strerror(errno)); |
strerror(errno)); |
|
|
/* sleep on some temporary kernel failures */ |
/* sleep on some temporary kernel failures */ |
|
|
} |
} |
|
|
for (i = 0; i < httpd->nsock; i++) { |
for (i = 0; i < httpd->nsock; i++) { |
if (daemon_poll_err(httpd, fd, i)) |
if (daemon_poll_err(httpd, i)) |
break; |
break; |
if (httpd->fds[i].revents == 0) |
if (httpd->fds[i].revents == 0) |
continue; |
continue; |
|
|
if (fd == -1) { |
if (fd == -1) { |
if (errno == EFAULT || |
if (errno == EFAULT || |
errno == EINVAL) |
errno == EINVAL) |
bozo_err(httpd, 1, "accept: %s", |
bozoerr(httpd, 1, "accept: %s", |
strerror(errno)); |
strerror(errno)); |
|
|
if (errno == ENOMEM || |
if (errno == ENOMEM || |
|
|
|
|
switch (fork()) { |
switch (fork()) { |
case -1: /* eep, failure */ |
case -1: /* eep, failure */ |
bozo_warn(httpd, "fork() failed, sleeping for " |
bozowarn(httpd, "fork() failed, sleeping for " |
"10 seconds: %s", strerror(errno)); |
"10 seconds: %s", strerror(errno)); |
close(fd); |
close(fd); |
sleep(10); |
sleep(10); |