From 51086f553bf423b2c94999d7f8239372f774f615 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Sun, 11 Nov 2007 16:09:45 +0000 Subject: [PATCH] * do non-blocking accept() * shut down on HUP instead of TERM; easier to debug. * kill & free our running sessions on shutdown --- webcit/Makefile.in | 4 +- webcit/context_loop.c | 9 ++++ webcit/debian/rules | 1 + webcit/sysdep.c | 95 +++++++++++++++++++++++++++++++++++++++ webcit/webcit.h | 17 ++++++- webcit/webserver.c | 100 +++++++++++++++++++++++++++++++++++++----- 6 files changed, 211 insertions(+), 15 deletions(-) create mode 100644 webcit/sysdep.c diff --git a/webcit/Makefile.in b/webcit/Makefile.in index 559583afd..44871bf2f 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -51,7 +51,7 @@ webserver: webserver.o context_loop.o tools.o ical_dezonify.o \ groupdav_main.o groupdav_get.o groupdav_propfind.o fmt_date.o \ groupdav_options.o autocompletion.o gettext.o tabs.o sieve.o \ groupdav_delete.o groupdav_put.o http_datestring.o setup_wizard.o \ - downloads.o addressbook_popup.o pushemail.o \ + downloads.o addressbook_popup.o pushemail.o sysdep.o \ $(LIBOBJS) $(CC) webserver.o context_loop.o tools.o cookie_conversion.o \ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o listsub.o \ @@ -63,7 +63,7 @@ webserver: webserver.o context_loop.o tools.o ical_dezonify.o \ groupdav_main.o groupdav_get.o groupdav_propfind.o groupdav_delete.o \ groupdav_options.o autocompletion.o tabs.o smtpqueue.o sieve.o \ groupdav_put.o http_datestring.o setup_wizard.o fmt_date.o \ - gettext.o downloads.o addressbook_popup.o pushemail.o \ + gettext.o downloads.o addressbook_popup.o pushemail.o sysdep.o \ $(LIBOBJS) $(LIBS) $(LDFLAGS) -o webserver .c.o: diff --git a/webcit/context_loop.c b/webcit/context_loop.c index b693ff992..f37fa6676 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -37,6 +37,15 @@ void free_attachments(struct wcsession *sess) { } } + +void shutdown_sessions(void) +{ + struct wcsession *sptr; + + for (sptr = SessionList; sptr != NULL; sptr = sptr->next) { + sptr->killthis = 1; + } +} /** * \brief what?????? */ diff --git a/webcit/debian/rules b/webcit/debian/rules index 1c5c346ab..c88c0403e 100755 --- a/webcit/debian/rules +++ b/webcit/debian/rules @@ -40,6 +40,7 @@ configure-stamp: --with-ssldir=/etc/ssl/webcit/ \ --with-zlib --with-ssl --with-libiconf \ --with-newt --with-included-gettext \ + --with-datadir=/var/run/citadel \ --enable-debug $(EXTRA_ARGS) $(PROFILE_ARGS) touch configure-stamp diff --git a/webcit/sysdep.c b/webcit/sysdep.c new file mode 100644 index 000000000..cbe41717e --- /dev/null +++ b/webcit/sysdep.c @@ -0,0 +1,95 @@ +/* + * $Id: sysdep.c 5691 2007-11-04 23:19:17Z dothebart $ + * + * Citadel "system dependent" stuff. + * See copyright.txt for copyright information. + * + * Here's where we (hopefully) have most parts of the Citadel server that + * would need to be altered to run the server in a non-POSIX environment. + * + * If we ever port to a different platform and either have multiple + * variants of this file or simply load it up with #ifdefs. + * + */ + +#include "sysdep.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_PTHREAD_H +#include +#endif +#include "webcit.h" +#include "sysdep.h" + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#ifndef HAVE_SNPRINTF +#include "snprintf.h" +#endif + +pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */ +pthread_key_t MyConKey; /* TSD key for MyContext() */ + +void InitialiseSemaphores(void) +{ + int i; + + /* Set up a bunch of semaphores to be used for critical sections */ + for (i=0; i + #include #include #ifdef HAVE_UNISTD_H @@ -404,7 +407,11 @@ enum { current_iconbar_menu, /**< view the icon menue */ current_iconbar_roomlist /**< view the roomtree */ }; - +enum { + S_SELECT, + S_SHUTDOWN, + MAX_SEMAPHORES +}; #define num_parms(source) num_tokens(source, '|') @@ -435,6 +442,12 @@ extern time_t if_modified_since; extern int follow_xff; void do_setup_wizard(void); + +void InitialiseSemaphores(void); +void begin_critical_section(int which_one); +void end_critical_section(int which_one); + + void stuff_to_cookie(char *cookie, int session, char *user, char *pass, char *room); void cookie_to_stuff(char *cookie, int *session, @@ -556,6 +569,8 @@ void display_confirm_delete_node(void); void delete_node(void); void display_add_node(void); void terminate_session(void); +void shutdown_sessions(void); +void do_housekeeping(void); void edit_me(void); void display_siteconfig(void); void siteconfig(void); diff --git a/webcit/webserver.c b/webcit/webserver.c index 55439dc69..89238741a 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -109,6 +109,8 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len) i = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + fcntl(s, F_SETFL, O_NONBLOCK);/// TODO + if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { lprintf(1, "Can't bind: %s\n", strerror(errno)); exit(WC_EXIT_BIND); @@ -474,10 +476,17 @@ pid_t current_child; void graceful_shutdown(int signum) { // kill(current_child, signum); char wd[SIZ]; + FILE *FD; + int fd; getcwd(wd, SIZ); - lprintf (1, "bye going down gracefull.[%s]\n", wd); + lprintf (1, "bye going down gracefull.[%d][%s]\n", signum, wd); + fd = msock; + msock = -1; time_to_die = 1; - exit(0); + FD=fdopen(fd, "a+"); + fflush (FD); + fclose (FD); + close(fd); } @@ -519,7 +528,8 @@ void start_daemon(char *pid_file) freopen("/dev/null", "r", stdin); freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); - signal(SIGTERM, graceful_shutdown_watcher); +/// signal(SIGTERM, graceful_shutdown_watcher); + signal(SIGHUP, graceful_shutdown_watcher); do { current_child = fork(); @@ -531,12 +541,15 @@ void start_daemon(char *pid_file) } else if (current_child == 0) { - signal(SIGTERM, graceful_shutdown); +//// signal(SIGTERM, graceful_shutdown); + signal(SIGHUP, graceful_shutdown); + return; /* continue starting webcit. */ } else { - signal(SIGTERM, SIG_IGN); +//// signal(SIGTERM, SIG_IGN); + signal(SIGHUP, SIG_IGN); if (pid_file) { fp = fopen(pid_file, "w"); if (fp != NULL) { @@ -735,7 +748,8 @@ int main(int argc, char **argv) start_daemon(pidfile); } else { - signal(SIGTERM, graceful_shutdown); +/// signal(SIGTERM, graceful_shutdown); + signal(SIGHUP, graceful_shutdown); } /** Tell 'em who's in da house */ @@ -806,6 +820,7 @@ int main(int argc, char **argv) if (pthread_key_create(&MyConKey, NULL) != 0) { lprintf(1, "Can't create TSD key: %s\n", strerror(errno)); } + InitialiseSemaphores (); /** * Set up a place to put thread-specific SSL data. @@ -876,15 +891,76 @@ void worker_entry(void) int ssock; int i = 0; int fail_this_transaction = 0; + int ret; + struct timeval tv; + fd_set readset, tempset; + + tv.tv_sec = 0; + tv.tv_usec = 10000; + FD_ZERO(&readset); + FD_SET(msock, &readset); do { /** Only one thread can accept at a time */ fail_this_transaction = 0; - ssock = accept(msock, NULL, 0); - if (ssock < 0) { - lprintf(2, "accept() failed: %s\n", - strerror(errno)); - } else { + ssock = -1; + errno = EAGAIN; + do { + ret = -1; /* just one at once should select... */ + begin_critical_section(S_SELECT); + + FD_ZERO(&tempset); + if (msock > 0) FD_SET(msock, &tempset); + tv.tv_sec = 0; + tv.tv_usec = 10000; + if (msock > 0) ret = select(msock+1, &tempset, NULL, NULL, &tv); + end_critical_section(S_SELECT); + if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) + {// EINTR and EAGAIN are thrown but not of interest. + lprintf(2, "accept() failed:%d %s\n", + errno, strerror(errno)); + } + else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset)) + {// Successfully selected, and still not shutting down? Accept! + ssock = accept(msock, NULL, 0); + } + + } while ((msock > 0) && (ssock < 0) && (time_to_die == 0)); + + if ((msock == -1)||(time_to_die)) + {// ok, we're going down. + int shutdown = 0; + + /* the first to come here will have to do the cleanup. + * make shure its realy just one. + */ + begin_critical_section(S_SHUTDOWN); + if (msock == -1) + { + msock = -2; + shutdown = 1; + } + end_critical_section(S_SHUTDOWN); + if (shutdown == 1) + {// we're the one to cleanup the mess. + lprintf(2, "I'm master shutdown: tagging sessions to be killed.\n"); + shutdown_sessions(); + lprintf(2, "master shutdown: waiting for others\n"); + sleeeeeeeeeep(1); // wait so some others might finish... + lprintf(2, "master shutdown: cleaning up sessions\n"); + do_housekeeping(); + lprintf(2, "master shutdown exiting!.\n"); + exit(0); + } + break; + } + if (ssock < 0 ) continue; + + if (msock < 0) { + if (ssock > 0) close (ssock); + lprintf(2, "inbetween."); + pthread_exit(NULL); + } else { // Got it? do some real work! /** Set the SO_REUSEADDR socket option */ i = 1; setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, @@ -920,7 +996,7 @@ void worker_entry(void) } while (!time_to_die); - lprintf (1, "bye"); + lprintf (1, "bye\n"); pthread_exit(NULL); } -- 2.30.2