]> code.citadel.org Git - citadel.git/blobdiff - citadel/sysdep.c
* Holy war on strlen: use IsEmptyStr where apropriate.
[citadel.git] / citadel / sysdep.c
index df4f714f2e1fab35e8f442f2b20188e2585d7ae6..1413675ea9d07b4bf46745a7249763c7c2eb3fb6 100644 (file)
@@ -23,6 +23,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
+#include <syslog.h>
 #include <sys/syslog.h>
 
 #if TIME_WITH_SYS_TIME
@@ -53,7 +54,6 @@
 #endif
 #include "citadel.h"
 #include "server.h"
-#include "serv_extensions.h"
 #include "sysdep_decls.h"
 #include "citserver.h"
 #include "support.h"
@@ -61,8 +61,7 @@
 #include "database.h"
 #include "housekeeping.h"
 #include "tools.h"
-#include "serv_crypto.h"
-#include "serv_fulltext.h"
+#include "modules/crypto/serv_crypto.h"        /* Needed for init_ssl, client_write_ssl, client_read_ssl, destruct_ssl */
 
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
@@ -94,12 +93,11 @@ struct CitContext masterCC;
 time_t last_purge = 0;                         /* Last dead session purge */
 static int num_threads = 0;                    /* Current number of threads */
 int num_sessions = 0;                          /* Current number of sessions */
-pthread_t indexer_thread_tid;
-pthread_t checkpoint_thread_tid;
 
 int syslog_facility = LOG_DAEMON;
 int enable_syslog = 0;
-extern int running_as_daemon;
+
+void DestroyWorkerList(void);
 
 /*
  * lprintf()  ...   Write logging information
@@ -155,6 +153,8 @@ void lprintf(enum LogLevel loglevel, const char *format, ...) {
 
 volatile int time_to_die = 0;
 volatile int shutdown_and_halt = 0;
+volatile int restart_server = 0;
+volatile int running_as_daemon = 0;
 
 static RETSIGTYPE signal_cleanup(int signum) {
        lprintf(CTDL_DEBUG, "Caught signal %d; shutting down.\n", signum);
@@ -162,7 +162,6 @@ static RETSIGTYPE signal_cleanup(int signum) {
        master_cleanup(signum);
 }
 
-
 /*
  * Some initialization stuff...
  */
@@ -289,7 +288,7 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len, char **errormes
                sin.sin_addr.s_addr = inet_addr(ip_addr);
        }
                                                                                
-       if (sin.sin_addr.s_addr == INADDR_NONE) {
+       if (sin.sin_addr.s_addr == !INADDR_ANY) {
                sin.sin_addr.s_addr = INADDR_ANY;
        }
 
@@ -477,6 +476,7 @@ struct CitContext *CreateNewContext(void) {
  * native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with
  * user-space buffering.
  */
+#ifndef HAVE_DARWIN
 #ifdef TCP_CORK
 #      define HAVE_TCP_BUFFERING
 #else
@@ -484,8 +484,8 @@ struct CitContext *CreateNewContext(void) {
 #              define HAVE_TCP_BUFFERING
 #              define TCP_CORK TCP_NOPUSH
 #      endif
-#endif
-
+#endif /* TCP_CORK */
+#endif /* HAVE_DARWIN */
 
 #ifdef HAVE_TCP_BUFFERING
 static unsigned on = 1, off = 0;
@@ -506,6 +506,16 @@ void flush_output(void) {
        setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
        setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
 }
+#elif HAVE_DARWIN
+/* Stub functions for Darwin/OS X where TCP buffering isn't liked at all */
+void buffer_output(void) {
+CC->buffering = 0;
+}
+void unbuffer_output(void) {
+CC->buffering = 0;
+}
+void flush_output(void) {
+}
 #else
 void buffer_output(void) {
        if (CC->buffering == 0) {
@@ -694,7 +704,7 @@ int client_getln(char *buf, int bufsize)
        /* Strip the trailing LF, and the trailing CR if present.
         */
        buf[i] = 0;
-       while ( (strlen(buf) > 0) && ((buf[strlen(buf)-1]==10) || (buf[strlen(buf)-1] == 13)) ) {
+       while ( (!IsEmptyStr(buf)) && ((buf[strlen(buf)-1]==10) || (buf[strlen(buf)-1] == 13)) ) {
                buf[strlen(buf)-1] = 0;
        }
        if (retval < 0) safestrncpy(buf, "000", bufsize);
@@ -709,6 +719,7 @@ int client_getln(char *buf, int bufsize)
 void sysdep_master_cleanup(void) {
        struct ServiceFunctionHook *serviceptr;
 
+/////  DestroyWorkerList();
        /*
         * close all protocol master sockets
         */
@@ -730,9 +741,25 @@ void sysdep_master_cleanup(void) {
                        unlink(serviceptr->sockpath);
                }
        }
+#ifdef HAVE_OPENSSL
+       destruct_ssl();
+#endif
+       serv_calendar_destroy();
+       CtdlDestroyProtoHooks();
+       CtdlDestroyDeleteHooks();
+       CtdlDestroyXmsgHooks();
+       CtdlDestroyNetprocHooks();
+       CtdlDestroyUserHooks();
+       CtdlDestroyMessageHook();
+       CtdlDestroyCleanupHooks();
+       CtdlDestroyFixedOutputHooks();  
+       CtdlDestroySessionHooks();
+       CtdlDestroyServiceHook();
 }
 
 
+
+
 /*
  * Terminate another session.
  * (This could justifiably be moved out of sysdep.c because it
@@ -765,6 +792,7 @@ void start_daemon(int unused) {
        int status = 0;
        pid_t child = 0;
        FILE *fp;
+       int do_restart = 0;
 
        current_child = 0;
 
@@ -776,11 +804,6 @@ void start_daemon(int unused) {
 
        child = fork();
        if (child != 0) {
-               fp = fopen(file_pid_file, "w");
-               if (fp != NULL) {
-                       fprintf(fp, "%d\n", child);
-                       fclose(fp);
-               }
                exit(0);
        }
        
@@ -789,7 +812,7 @@ void start_daemon(int unused) {
        signal(SIGQUIT, SIG_IGN);
 
        setsid();
-//     umask(0);
+       umask(0);
         freopen("/dev/null", "r", stdin);
         freopen("/dev/null", "w", stdout);
         freopen("/dev/null", "w", stderr);
@@ -809,14 +832,44 @@ void start_daemon(int unused) {
                }
        
                else {
+                       fp = fopen(file_pid_file, "w");
+                       if (fp != NULL) {
+                               fprintf(fp, ""F_PID_T"\n", child);
+                               fclose(fp);
+                       }
                        waitpid(current_child, &status, 0);
                }
 
-       } while (status != 0);
+               do_restart = 0;
 
-       unlink(file_pid_file);
-       exit(0);
+               /* Did the main process exit with an actual exit code? */
+               if (WIFEXITED(status)) {
+
+                       /* Exit code 0 means the watcher should exit */
+                       if (WEXITSTATUS(status) == 0) {
+                               do_restart = 0;
+                       }
+
+                       /* Exit code 101-109 means the watcher should exit */
+                       else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
+                               do_restart = 0;
+                       }
+
+                       /* Any other exit code means we should restart. */
+                       else {
+                               do_restart = 1;
+                       }
+               }
 
+               /* Any other type of termination (signals, etc.) should also restart. */
+               else {
+                       do_restart = 1;
+               }
+
+       } while (do_restart);
+
+       unlink(file_pid_file);
+       exit(WEXITSTATUS(status));
 }
 
 
@@ -891,10 +944,40 @@ void create_worker(void) {
        pthread_attr_destroy(&attr);
 }
 
+void DestroyWorkerList(void)
+{
+       struct CitContext *ptr;         /* general-purpose utility pointer */
+       struct CitContext *rem = NULL;  /* list of sessions to be destroyed */
+
+       begin_critical_section(S_SESSION_TABLE);
+       ptr = ContextList;
+       while (ptr != NULL){
+               /* Remove the session from the active list */
+               rem = ptr->next;
+               --num_sessions;
+               
+               lprintf(CTDL_DEBUG, "Purging session %d\n", rem->cs_pid);
+               end_critical_section(S_SESSION_TABLE);
+               RemoveContext(ptr);
+               begin_critical_section(S_SESSION_TABLE);
+               free (ptr);
+               ptr = rem;
+       }
+       end_critical_section(S_SESSION_TABLE);
+
+       struct worker_node *cur, *p;
+       cur = worker_list;
+       while (cur != NULL)
+       {
+               p = cur->next;
+               free (cur);
+               cur = p;
+       }
+       worker_list = NULL;
+}
 
 /*
- * Create the indexer thread and begin its operation.
- * Then create the checkpoint thread and begin its operation.
+ * Create the maintenance threads and begin their operation.
  */
 void create_maintenance_threads(void) {
        int ret;
@@ -917,15 +1000,23 @@ void create_maintenance_threads(void) {
                pthread_attr_destroy(&attr);
                return;
        }
+       
+       struct MaintenanceThreadHook *fcn;
 
-       if ((ret = pthread_create(&indexer_thread_tid, &attr, indexer_thread, NULL) != 0)) {
-               lprintf(CTDL_ALERT, "Can't create thread: %s\n", strerror(ret));
-       }
+       lprintf(CTDL_DEBUG, "Performing startup of maintenance thread hooks\n");
 
-       if ((ret = pthread_create(&checkpoint_thread_tid, &attr, checkpoint_thread, NULL) != 0)) {
-               lprintf(CTDL_ALERT, "Can't create thread: %s\n", strerror(ret));
+       for (fcn = MaintenanceThreadHookTable; fcn != NULL; fcn = fcn->next) {
+               if ((ret = pthread_create(&(fcn->MaintenanceThread_tid), &attr, fcn->fcn_ptr, NULL) != 0)) {
+                       lprintf(CTDL_ALERT, "Can't create thread: %s\n", strerror(ret));
+               }
+               else
+               {
+                       lprintf(CTDL_NOTICE, "Spawned a new maintenance thread \"%s\" (%ld). \n", fcn->name,
+                               fcn->MaintenanceThread_tid);
+               }
        }
 
+
        pthread_attr_destroy(&attr);
 }
 
@@ -1223,7 +1314,7 @@ SKIP_SELECT:
                do_housekeeping();
                check_sched_shutdown();
        }
-
+       if (con != NULL) free (con);//// TODO: could this harm other threads? 
        /* If control reaches this point, the server is shutting down */        
        return(NULL);
 }