X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fsysdep.c;h=d634c5496a01a21dfac30edc6be95564ef9fd9ef;hb=7e5d9e93cc7fdc560eac95647fe329d818444226;hp=12ef309cc88531231e0c7acc2e53044d44491477;hpb=0f212bcc8c237b51df2583a7921aa36ce13e15e2;p=citadel.git diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 12ef309cc..d634c5496 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -84,7 +84,7 @@ struct igheap *igheap = NULL; #endif -pthread_key_t MyConKey; /* TSD key for MyContext() */ +citthread_key_t MyConKey; /* TSD key for MyContext() */ int verbosity = DEFAULT_VERBOSITY; /* Logging level */ @@ -97,30 +97,16 @@ int enable_syslog = 0; /* - * 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 + * CtdlLogPrintf() ... Write logging information */ - -void CtdlLogPrintf(enum LogLevel loglevel, const char *format, ...) -{ +void CtdlLogPrintf(enum LogLevel loglevel, const char *format, ...) { va_list arg_ptr; va_start(arg_ptr, format); - vlprintf(loglevel, format, arg_ptr); + vCtdlLogPrintf(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) +void vCtdlLogPrintf(enum LogLevel loglevel, const char *format, va_list arg_ptr) { char buf[SIZ], buf2[SIZ]; @@ -155,7 +141,7 @@ void vlprintf(enum LogLevel loglevel, const char *format, va_list arg_ptr) tim.tm_mday, tim.tm_hour, tim.tm_min, tim.tm_sec, (long)tv.tv_usec); } - vsprintf(buf2, format, arg_ptr); + vsnprintf(buf2, SIZ, format, arg_ptr); fprintf(stderr, "%s%s", buf, buf2); fflush(stderr); @@ -174,16 +160,15 @@ volatile int restart_server = 0; volatile int running_as_daemon = 0; static RETSIGTYPE signal_cleanup(int signum) { - CtdlLogPrintf(CTDL_DEBUG, "Caught signal %d; shutting down.\n", signum); #ifdef THREADS_USESIGNALS if (CT) - { - CtdlLogPrintf(CTDL_DEBUG, "Thread \"%s\" caught signal %d.\n", CT->name, signum); CT->signal = signum; - } else #endif + { + CtdlLogPrintf(CTDL_DEBUG, "Caught signal %d; shutting down.\n", signum); exit_signal = signum; + } } @@ -216,7 +201,7 @@ void init_sysdep(void) { * CitContext structure (in the ContextList linked list) of the * session to which the calling thread is currently bound. */ - if (pthread_key_create(&MyConKey, NULL) != 0) { + if (citthread_key_create(&MyConKey, NULL) != 0) { CtdlLogPrintf(CTDL_CRIT, "Can't create TSD key: %s\n", strerror(errno)); } @@ -414,7 +399,7 @@ struct CitContext *MyContext(void) { register struct CitContext *c; - return ((c = (struct CitContext *) pthread_getspecific(MyConKey), + return ((c = (struct CitContext *) citthread_getspecific(MyConKey), c == NULL) ? &masterCC : c ); } @@ -460,6 +445,24 @@ struct CitContext *CreateNewContext(void) { } +struct CitContext *CtdlGetContextArray(int *count) +{ + int nContexts, i; + struct CitContext *nptr, *cptr; + + nContexts = num_sessions; + nptr = malloc(sizeof(struct CitContext) * nContexts); + if (!nptr) + return NULL; + begin_critical_section(S_SESSION_TABLE); + for (cptr = ContextList, i=0; cptr != NULL && i < nContexts; cptr = cptr->next, i++) + memcpy(&nptr[i], cptr, sizeof (struct CitContext)); + end_critical_section (S_SESSION_TABLE); + + *count = i; + return nptr; +} + /* * The following functions implement output buffering. If the kernel supplies * native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with @@ -540,14 +543,16 @@ void unbuffer_output(void) { /* * client_write() ... Send binary data to the client. */ -void client_write(char *buf, int nbytes) +int client_write(char *buf, int nbytes) { int bytes_written = 0; int retval; #ifndef HAVE_TCP_BUFFERING int old_buffer_len = 0; #endif + fd_set wset; t_context *Ctx; + int fdflags; Ctx = CC; if (Ctx->redirect_buffer != NULL) { @@ -559,7 +564,7 @@ void client_write(char *buf, int nbytes) memcpy(&Ctx->redirect_buffer[Ctx->redirect_len], buf, nbytes); Ctx->redirect_len += nbytes; Ctx->redirect_buffer[Ctx->redirect_len] = 0; - return; + return 0; } #ifndef HAVE_TCP_BUFFERING @@ -569,7 +574,7 @@ void client_write(char *buf, int nbytes) Ctx->buffer_len += nbytes; Ctx->output_buffer = realloc(Ctx->output_buffer, Ctx->buffer_len); memcpy(&Ctx->output_buffer[old_buffer_len], buf, nbytes); - return; + return 0; } #endif @@ -578,11 +583,27 @@ void client_write(char *buf, int nbytes) #ifdef HAVE_OPENSSL if (Ctx->redirect_ssl) { client_write_ssl(buf, nbytes); - return; + return 0; } #endif + fdflags = fcntl(Ctx->client_socket, F_GETFL); + while (bytes_written < nbytes) { + if ((fdflags & O_NONBLOCK) == O_NONBLOCK) { + FD_ZERO(&wset); + FD_SET(Ctx->client_socket, &wset); + if (select(1, NULL, &wset, NULL, NULL) == -1) { + CtdlLogPrintf(CTDL_ERR, + "client_write(%d bytes) select failed: %s (%d)\n", + nbytes - bytes_written, + strerror(errno), errno); + cit_backtrace(); + Ctx->kill_me = 1; + return -1; + } + } + retval = write(Ctx->client_socket, &buf[bytes_written], nbytes - bytes_written); if (retval < 1) { @@ -593,10 +614,11 @@ void client_write(char *buf, int nbytes) cit_backtrace(); // CtdlLogPrintf(CTDL_DEBUG, "Tried to send: %s", &buf[bytes_written]); Ctx->kill_me = 1; - return; + return -1; } bytes_written = bytes_written + retval; } + return 0; } @@ -648,6 +670,15 @@ int client_read_to(char *buf, int bytes, int timeout) retval = select( (fd)+1, &rfds, NULL, NULL, &tv); + if (retval < 0) + { + if (errno == EINTR) + { + CtdlLogPrintf(CTDL_DEBUG, "Interrupted select().\n"); + CC->kill_me = 1; + return (-1); + } + } if (FD_ISSET(fd, &rfds) == 0) { return(0); @@ -738,7 +769,7 @@ void context_cleanup(void) rem = ptr->next; --num_sessions; - lprintf(CTDL_DEBUG, "Purging session %d\n", ptr->cs_pid); + CtdlLogPrintf(CTDL_DEBUG, "Purging session %d\n", ptr->cs_pid); RemoveContext(ptr); free (ptr); ptr = rem; @@ -883,11 +914,7 @@ void start_daemon(int unused) { else { fp = fopen(file_pid_file, "w"); if (fp != NULL) { - /* - * 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); + fprintf(fp, ""F_PID_T"\n", getpid()); fclose(fp); } waitpid(current_child, &status, 0); @@ -1030,7 +1057,7 @@ void InitializeMasterCC(void) { * Bind a thread to a context. (It's inline merely to speed things up.) */ INLINE void become_session(struct CitContext *which_con) { - pthread_setspecific(MyConKey, (void *)which_con ); + citthread_setspecific(MyConKey, (void *)which_con ); } @@ -1129,8 +1156,8 @@ do_select: force_purge = 0; tv.tv_usec = 0; retval = CtdlThreadSelect(highest + 1, &readfds, NULL, NULL, &tv); } - - if (CtdlThreadCheckStop()) return(NULL); + else + return NULL; /* Now figure out who made this select() unblock. * First, check for an error or exit condition. @@ -1144,12 +1171,14 @@ do_select: force_purge = 0; if (errno != EINTR) { CtdlLogPrintf(CTDL_EMERG, "Exiting (%s)\n", strerror(errno)); CtdlThreadStopAll(); - } else if (!CtdlThreadCheckStop()) { - CtdlLogPrintf(CTDL_DEBUG, "Un handled select failure.\n"); + } else { + CtdlLogPrintf(CTDL_DEBUG, "Interrupted CtdlThreadSelect.\n"); + if (CtdlThreadCheckStop()) return(NULL); goto do_select; } } else if(retval == 0) { + if (CtdlThreadCheckStop()) return(NULL); goto SKIP_SELECT; } /* Next, check to see if it's a new client connecting