X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fsysdep.c;h=cc54d0bae8f141bdaf782ae0afbb37d5ae03eb28;hb=584b4fafe7947d7c8432b5d1896553ba3759491f;hp=761b225c746ca6620b3a8f3c6ac9029af952c5f5;hpb=01cc19a4c2da27b4db0e980ccd3ca54d834319c8;p=citadel.git diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 761b225c7..cc54d0bae 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -61,8 +61,8 @@ #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 */ +#include "ecrash.h" #ifdef HAVE_SYS_SELECT_H #include @@ -94,25 +94,43 @@ 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); + +/* + * Create an interface to lprintf that follows the coding convention. + * This is here until such time as we have replaced all calls to lprintf with CtdlLogPrintf + */ + +void CtdlLogPrintf(enum LogLevel loglevel, const char *format, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, format); + vlprintf(loglevel, format, arg_ptr); + va_end(arg_ptr); +} + + /* * lprintf() ... Write logging information */ void lprintf(enum LogLevel loglevel, const char *format, ...) { va_list arg_ptr; + va_start(arg_ptr, format); + vlprintf(loglevel, format, arg_ptr); + va_end(arg_ptr); +} + +void vlprintf(enum LogLevel loglevel, const char *format, va_list arg_ptr) +{ + char buf[SIZ], buf2[SIZ]; if (enable_syslog) { - va_start(arg_ptr, format); - vsyslog((syslog_facility | loglevel), format, arg_ptr); - va_end(arg_ptr); + vsyslog((syslog_facility | loglevel), format, arg_ptr); } /* stderr output code */ @@ -129,22 +147,22 @@ void lprintf(enum LogLevel loglevel, const char *format, ...) { unixtime = tv.tv_sec; localtime_r(&unixtime, &tim); if (CC->cs_pid != 0) { - fprintf(stderr, + sprintf(buf, "%04d/%02d/%02d %2d:%02d:%02d.%06ld [%3d] ", tim.tm_year + 1900, tim.tm_mon + 1, tim.tm_mday, tim.tm_hour, tim.tm_min, tim.tm_sec, (long)tv.tv_usec, CC->cs_pid); } else { - fprintf(stderr, + sprintf(buf, "%04d/%02d/%02d %2d:%02d:%02d.%06ld ", tim.tm_year + 1900, tim.tm_mon + 1, tim.tm_mday, tim.tm_hour, tim.tm_min, tim.tm_sec, (long)tv.tv_usec); } - va_start(arg_ptr, format); - vfprintf(stderr, format, arg_ptr); - va_end(arg_ptr); + vsprintf(buf2, format, arg_ptr); + + fprintf(stderr, "%s%s", buf, buf2); fflush(stderr); } } @@ -157,6 +175,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); @@ -164,11 +184,25 @@ static RETSIGTYPE signal_cleanup(int signum) { master_cleanup(signum); } + + + +void InitialiseSemaphores(void) +{ + int i; + + /* Set up a bunch of semaphores to be used for critical sections */ + for (i=0; iclient_socket, IPPROTO_TCP, TCP_CORK, &off, 4); setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4); } -#elif HAVE_DARWIN +#else +#ifdef HAVE_DARWIN /* Stub functions for Darwin/OS X where TCP buffering isn't liked at all */ void buffer_output(void) { -CC->buffering = 0; + CC->buffering = 0; } void unbuffer_output(void) { -CC->buffering = 0; + CC->buffering = 0; } void flush_output(void) { } @@ -544,7 +574,8 @@ void unbuffer_output(void) { CC->output_buffer = NULL; } } -#endif +#endif /* HAVE_DARWIN */ +#endif /* HAVE_TCP_BUFFERING */ @@ -558,26 +589,28 @@ void client_write(char *buf, int nbytes) #ifndef HAVE_TCP_BUFFERING int old_buffer_len = 0; #endif - - if (CC->redirect_buffer != NULL) { - if ((CC->redirect_len + nbytes + 2) >= CC->redirect_alloc) { - CC->redirect_alloc = (CC->redirect_alloc * 2) + nbytes; - CC->redirect_buffer = realloc(CC->redirect_buffer, - CC->redirect_alloc); + t_context *Ctx; + + Ctx = CC; + if (Ctx->redirect_buffer != NULL) { + if ((Ctx->redirect_len + nbytes + 2) >= Ctx->redirect_alloc) { + Ctx->redirect_alloc = (Ctx->redirect_alloc * 2) + nbytes; + Ctx->redirect_buffer = realloc(Ctx->redirect_buffer, + Ctx->redirect_alloc); } - memcpy(&CC->redirect_buffer[CC->redirect_len], buf, nbytes); - CC->redirect_len += nbytes; - CC->redirect_buffer[CC->redirect_len] = 0; + memcpy(&Ctx->redirect_buffer[Ctx->redirect_len], buf, nbytes); + Ctx->redirect_len += nbytes; + Ctx->redirect_buffer[Ctx->redirect_len] = 0; return; } #ifndef HAVE_TCP_BUFFERING /* If we're buffering for later, do that now. */ - if (CC->buffering) { - old_buffer_len = CC->buffer_len; - CC->buffer_len += nbytes; - CC->output_buffer = realloc(CC->output_buffer, CC->buffer_len); - memcpy(&CC->output_buffer[old_buffer_len], buf, nbytes); + if (Ctx->buffering) { + old_buffer_len = Ctx->buffer_len; + Ctx->buffer_len += nbytes; + Ctx->output_buffer = realloc(Ctx->output_buffer, Ctx->buffer_len); + memcpy(&Ctx->output_buffer[old_buffer_len], buf, nbytes); return; } #endif @@ -585,21 +618,23 @@ void client_write(char *buf, int nbytes) /* Ok, at this point we're not buffering. Go ahead and write. */ #ifdef HAVE_OPENSSL - if (CC->redirect_ssl) { + if (Ctx->redirect_ssl) { client_write_ssl(buf, nbytes); return; } #endif while (bytes_written < nbytes) { - retval = write(CC->client_socket, &buf[bytes_written], + retval = write(Ctx->client_socket, &buf[bytes_written], nbytes - bytes_written); if (retval < 1) { lprintf(CTDL_ERR, "client_write(%d bytes) failed: %s (%d)\n", nbytes - bytes_written, strerror(errno), errno); - CC->kill_me = 1; + cit_backtrace(); + lprintf(CTDL_DEBUG, "Tried to send: %s", &buf[bytes_written]); + Ctx->kill_me = 1; return; } bytes_written = bytes_written + retval; @@ -636,6 +671,7 @@ int client_read_to(char *buf, int bytes, int timeout) { int len,rlen; fd_set rfds; + int fd; struct timeval tv; int retval; @@ -645,20 +681,21 @@ int client_read_to(char *buf, int bytes, int timeout) } #endif len = 0; + fd = CC->client_socket; while(lenclient_socket, &rfds); + FD_SET(fd, &rfds); tv.tv_sec = timeout; tv.tv_usec = 0; - retval = select( (CC->client_socket)+1, - &rfds, NULL, NULL, &tv); + retval = select( (fd)+1, + &rfds, NULL, NULL, &tv); - if (FD_ISSET(CC->client_socket, &rfds) == 0) { + if (FD_ISSET(fd, &rfds) == 0) { return(0); } - rlen = read(CC->client_socket, &buf[len], bytes-len); + rlen = read(fd, &buf[len], bytes-len); if (rlen<1) { /* The socket has been disconnected! */ CC->kill_me = 1; @@ -706,10 +743,13 @@ 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)) ) { - buf[strlen(buf)-1] = 0; + while ( (i > 0) + && ( (buf[i - 1]==13) + || ( buf[i - 1]==10)) ) { + i--; + buf[i] = 0; } - if (retval < 0) safestrncpy(buf, "000", bufsize); + if (retval < 0) safestrncpy(&buf[i], "000", bufsize - i); return(retval); } @@ -757,6 +797,9 @@ void sysdep_master_cleanup(void) { CtdlDestroyFixedOutputHooks(); CtdlDestroySessionHooks(); CtdlDestroyServiceHook(); + #ifdef HAVE_BACKTRACE + eCrash_Uninit(); + #endif } @@ -836,7 +879,11 @@ void start_daemon(int unused) { else { fp = fopen(file_pid_file, "w"); if (fp != NULL) { - fprintf(fp, ""F_PID_T"\n", child); + /* + * NB.. The pid file contains the pid of the actual server. + * This is not the pid of the watcher process + */ + fprintf(fp, ""F_PID_T"\n", current_child); fclose(fp); } waitpid(current_child, &status, 0); @@ -979,8 +1026,7 @@ void DestroyWorkerList(void) } /* - * 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; @@ -1003,17 +1049,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); + } } - lprintf(CTDL_NOTICE, "Spawned indexer (%ld) and checkpoint (%ld) thread. \n", - indexer_thread_tid, checkpoint_thread_tid); + pthread_attr_destroy(&attr); } @@ -1136,6 +1188,10 @@ void *worker_thread(void *arg) { cdb_allocate_tsd(); + // Register for tracing + #ifdef HAVE_BACKTRACE + eCrash_RegisterThread("WorkerThread", 0); + #endif while (!time_to_die) { /* make doubly sure we're not holding any stale db handles @@ -1240,7 +1296,9 @@ do_select: force_purge = 0; serviceptr->h_command_function; con->h_async_function = serviceptr->h_async_function; - + con->ServiceName = + serviceptr->ServiceName; + /* Determine whether it's a local socket */ if (serviceptr->sockpath != NULL) con->is_local_socket = 1; @@ -1313,6 +1371,9 @@ SKIP_SELECT: } if (con != NULL) free (con);//// TODO: could this harm other threads? /* If control reaches this point, the server is shutting down */ + #ifdef HAVE_BACKTRACE + eCrash_UnregisterThread(); + #endif return(NULL); }