mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
Implement --pidfile and move clean shutdown into main()
This commit is contained in:
parent
42833fb312
commit
4fed6d0665
@ -49,6 +49,7 @@ static const int debug = 1;
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <libutil.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -247,10 +248,14 @@ static int sockin = -1; /* socket to accept connections from */
|
|||||||
static char *wwwroot = NULL; /* a path name */
|
static char *wwwroot = NULL; /* a path name */
|
||||||
static char *logfile_name = NULL; /* NULL = no logging */
|
static char *logfile_name = NULL; /* NULL = no logging */
|
||||||
static FILE *logfile = NULL;
|
static FILE *logfile = NULL;
|
||||||
|
static char *pidfile_name = NULL; /* NULL = no pidfile */
|
||||||
|
static struct pidfh *pidfile = NULL;
|
||||||
static int want_chroot = 0, want_accf = 0;
|
static int want_chroot = 0, want_accf = 0;
|
||||||
static uint32_t num_requests = 0;
|
static uint32_t num_requests = 0;
|
||||||
static uint64_t total_in = 0, total_out = 0;
|
static uint64_t total_in = 0, total_out = 0;
|
||||||
|
|
||||||
|
static int running = 1; /* signal handler sets this to false */
|
||||||
|
|
||||||
#define INVALID_UID ((uid_t) -1)
|
#define INVALID_UID ((uid_t) -1)
|
||||||
#define INVALID_GID ((gid_t) -1)
|
#define INVALID_GID ((gid_t) -1)
|
||||||
|
|
||||||
@ -923,13 +928,17 @@ static void usage(void)
|
|||||||
"\t\tParses specified file for extension-MIME associations.\n"
|
"\t\tParses specified file for extension-MIME associations.\n"
|
||||||
"\n");
|
"\n");
|
||||||
printf(
|
printf(
|
||||||
"\t--uid uid, --gid gid\n"
|
"\t--uid uid/uname, --gid gid/gname (default: don't privdrop)\n"
|
||||||
"\t\tDrops privileges to given uid:gid after initialization.\n"
|
"\t\tDrops privileges to given uid:gid after initialization.\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
printf(
|
||||||
|
"\t--pidfile filename (default: no pidfile)\n"
|
||||||
|
"\t\tWrite PID to the specified file.\n"
|
||||||
|
"\n");
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
printf(
|
printf(
|
||||||
"\t--accf\n"
|
"\t--accf (default: don't use acceptfilter)\n"
|
||||||
"\t\tUse acceptfilter.\n"
|
"\t\tUse acceptfilter. Needs the accf_http module loaded.\n"
|
||||||
"\n");
|
"\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1043,6 +1052,12 @@ static void parse_commandline(const int argc, char *argv[])
|
|||||||
if (g == NULL) errx(1, "no such gid: `%s'", argv[i]);
|
if (g == NULL) errx(1, "no such gid: `%s'", argv[i]);
|
||||||
drop_gid = g->gr_gid;
|
drop_gid = g->gr_gid;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(argv[i], "--pidfile") == 0)
|
||||||
|
{
|
||||||
|
if (++i >= argc)
|
||||||
|
errx(1, "missing filename after --pidfile");
|
||||||
|
pidfile_name = argv[i];
|
||||||
|
}
|
||||||
else if (strcmp(argv[i], "--accf") == 0)
|
else if (strcmp(argv[i], "--accf") == 0)
|
||||||
{
|
{
|
||||||
want_accf = 1;
|
want_accf = 1;
|
||||||
@ -2233,7 +2248,12 @@ static void httpd_poll(void)
|
|||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (select_ret == -1) err(1, "select()");
|
if (select_ret == -1) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
return; /* interrupted by signal */
|
||||||
|
else
|
||||||
|
err(1, "select() failed");
|
||||||
|
}
|
||||||
|
|
||||||
/* poll connections that select() says need attention */
|
/* poll connections that select() says need attention */
|
||||||
if (FD_ISSET(sockin, &recv_set)) accept_connection();
|
if (FD_ISSET(sockin, &recv_set)) accept_connection();
|
||||||
@ -2262,44 +2282,11 @@ static void httpd_poll(void)
|
|||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
* Close all sockets and FILEs and exit.
|
* Close all sockets and FILEs and exit.
|
||||||
*/
|
*/
|
||||||
static void exit_quickly(int sig)
|
static void
|
||||||
|
stop_running(int sig)
|
||||||
{
|
{
|
||||||
struct connection *conn, *next;
|
running = 0;
|
||||||
struct rusage r;
|
fprintf(stderr, "\ncaught %s, stopping\n", strsignal(sig));
|
||||||
size_t i;
|
|
||||||
|
|
||||||
printf("\ncaught %s, cleaning up...", strsignal(sig)); fflush(stdout);
|
|
||||||
/* close and free connections */
|
|
||||||
LIST_FOREACH_SAFE(conn, &connlist, entries, next)
|
|
||||||
{
|
|
||||||
LIST_REMOVE(conn, entries);
|
|
||||||
free_connection(conn);
|
|
||||||
free(conn);
|
|
||||||
}
|
|
||||||
xclose(sockin);
|
|
||||||
if (logfile != NULL) fclose(logfile);
|
|
||||||
|
|
||||||
/* free mime_map */
|
|
||||||
for (i=0; i<mime_map_size; i++)
|
|
||||||
{
|
|
||||||
free(mime_map[i].extension);
|
|
||||||
free(mime_map[i].mimetype);
|
|
||||||
}
|
|
||||||
free(mime_map);
|
|
||||||
free(keep_alive_field);
|
|
||||||
free(wwwroot);
|
|
||||||
printf("done!\n");
|
|
||||||
|
|
||||||
getrusage(RUSAGE_SELF, &r);
|
|
||||||
printf("CPU time used: %u.%02u user, %u.%02u system\n",
|
|
||||||
(unsigned int)r.ru_utime.tv_sec,
|
|
||||||
(unsigned int)(r.ru_utime.tv_usec/10000),
|
|
||||||
(unsigned int)r.ru_stime.tv_sec,
|
|
||||||
(unsigned int)(r.ru_stime.tv_usec/10000)
|
|
||||||
);
|
|
||||||
printf("Requests: %u\n", num_requests);
|
|
||||||
printf("Bytes: %llu in, %llu out\n", total_in, total_out);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2319,20 +2306,35 @@ int main(int argc, char *argv[])
|
|||||||
xasprintf(&keep_alive_field, "Keep-Alive: timeout=%d\r\n", idletime);
|
xasprintf(&keep_alive_field, "Keep-Alive: timeout=%d\r\n", idletime);
|
||||||
init_sockin();
|
init_sockin();
|
||||||
|
|
||||||
|
/* create pidfile */
|
||||||
|
if (pidfile_name) {
|
||||||
|
pid_t otherpid;
|
||||||
|
pidfile = pidfile_open(pidfile_name, 0600, &otherpid);
|
||||||
|
if (pidfile == NULL) {
|
||||||
|
if (errno == EEXIST)
|
||||||
|
errx(1, "Daemon already running with PID %d", (int)otherpid);
|
||||||
|
else
|
||||||
|
err(1, "Can't create pidfile \"%s\"", pidfile_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* open logfile */
|
/* open logfile */
|
||||||
if (logfile_name != NULL)
|
if (logfile_name != NULL)
|
||||||
{
|
{
|
||||||
logfile = fopen(logfile_name, "ab");
|
logfile = fopen(logfile_name, "ab");
|
||||||
if (logfile == NULL) err(1, "fopen(\"%s\")", logfile_name);
|
if (logfile == NULL)
|
||||||
|
err(1, "opening logfile: fopen(\"%s\")", logfile_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* signals */
|
/* signals */
|
||||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||||
err(1, "signal(ignore SIGPIPE)");
|
err(1, "signal(ignore SIGPIPE)");
|
||||||
if (signal(SIGINT, exit_quickly) == SIG_ERR)
|
if (signal(SIGINT, stop_running) == SIG_ERR)
|
||||||
err(1, "signal(SIGINT)");
|
err(1, "signal(SIGINT)");
|
||||||
if (signal(SIGQUIT, exit_quickly) == SIG_ERR)
|
if (signal(SIGQUIT, stop_running) == SIG_ERR)
|
||||||
err(1, "signal(SIGQUIT)");
|
err(1, "signal(SIGQUIT)");
|
||||||
|
if (signal(SIGTERM, stop_running) == SIG_ERR)
|
||||||
|
err(1, "signal(SIGTERM)");
|
||||||
|
|
||||||
/* security */
|
/* security */
|
||||||
if (want_chroot)
|
if (want_chroot)
|
||||||
@ -2352,9 +2354,59 @@ int main(int argc, char *argv[])
|
|||||||
printf("set uid to %d\n", drop_uid);
|
printf("set uid to %d\n", drop_uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) httpd_poll();
|
/* FIXME: daemonize here */
|
||||||
|
|
||||||
return EXIT_FAILURE; /* unreachable */
|
if (pidfile) pidfile_write(pidfile);
|
||||||
|
|
||||||
|
/* main loop */
|
||||||
|
while (running) httpd_poll();
|
||||||
|
|
||||||
|
/* clean exit */
|
||||||
|
pidfile_remove(pidfile);
|
||||||
|
|
||||||
|
/* close and free connections */
|
||||||
|
{
|
||||||
|
struct connection *conn, *next;
|
||||||
|
|
||||||
|
LIST_FOREACH_SAFE(conn, &connlist, entries, next)
|
||||||
|
{
|
||||||
|
LIST_REMOVE(conn, entries);
|
||||||
|
free_connection(conn);
|
||||||
|
free(conn);
|
||||||
|
}
|
||||||
|
xclose(sockin);
|
||||||
|
if (logfile != NULL) fclose(logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free the mallocs */
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i=0; i<mime_map_size; i++)
|
||||||
|
{
|
||||||
|
free(mime_map[i].extension);
|
||||||
|
free(mime_map[i].mimetype);
|
||||||
|
}
|
||||||
|
free(mime_map);
|
||||||
|
free(keep_alive_field);
|
||||||
|
free(wwwroot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* usage stats */
|
||||||
|
{
|
||||||
|
struct rusage r;
|
||||||
|
|
||||||
|
getrusage(RUSAGE_SELF, &r);
|
||||||
|
printf("CPU time used: %u.%02u user, %u.%02u system\n",
|
||||||
|
(unsigned int)r.ru_utime.tv_sec,
|
||||||
|
(unsigned int)(r.ru_utime.tv_usec/10000),
|
||||||
|
(unsigned int)r.ru_stime.tv_sec,
|
||||||
|
(unsigned int)(r.ru_stime.tv_usec/10000)
|
||||||
|
);
|
||||||
|
printf("Requests: %u\n", num_requests);
|
||||||
|
printf("Bytes: %llu in, %llu out\n", total_in, total_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set tabstop=4 shiftwidth=4 expandtab tw=78: */
|
/* vim:set tabstop=4 shiftwidth=4 expandtab tw=78: */
|
||||||
|
Loading…
Reference in New Issue
Block a user