X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fsysdep.c;h=f4e20d72ebb3c6bda71acff9ecad6fce5d95f1e9;hb=11219dbc3e638e7ee47feffbbb7d63588d7dd77f;hp=b71c068a2819e4f359d47c1b64109f46bf346c90;hpb=acfcc89045bbdc80ae7614ca3ee38303ae98f08b;p=citadel.git diff --git a/citadel/sysdep.c b/citadel/sysdep.c index b71c068a2..f4e20d72e 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -12,10 +12,6 @@ * */ -#ifdef DLL_EXPORT -#define IN_LIBCIT -#endif - #include "sysdep.h" #include #include @@ -99,8 +95,9 @@ 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 = (-1); +int syslog_facility = LOG_DAEMON; int enable_syslog = 0; extern int running_as_daemon; @@ -112,7 +109,7 @@ void lprintf(enum LogLevel loglevel, const char *format, ...) { if (enable_syslog) { va_start(arg_ptr, format); - vsyslog(loglevel, format, arg_ptr); + vsyslog((syslog_facility | loglevel), format, arg_ptr); va_end(arg_ptr); } @@ -157,6 +154,7 @@ void lprintf(enum LogLevel loglevel, const char *format, ...) { */ volatile int time_to_die = 0; +volatile int shutdown_and_halt = 0; static RETSIGTYPE signal_cleanup(int signum) { lprintf(CTDL_DEBUG, "Caught signal %d; shutting down.\n", signum); @@ -250,6 +248,7 @@ void begin_critical_section(int which_one) #ifdef DEBUG_MEMORY_LEAKS && (which_one != S_DEBUGMEMLEAKS) #endif + && (which_one != S_RPLIST) ) { cdb_check_handles(); } @@ -271,7 +270,7 @@ void end_critical_section(int which_one) * a TCP port. The server shuts down if the bind fails. * */ -int ig_tcp_server(char *ip_addr, int port_number, int queue_len) +int ig_tcp_server(char *ip_addr, int port_number, int queue_len, char **errormessage) { struct sockaddr_in sin; int s, i; @@ -297,8 +296,11 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len) s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) { - lprintf(CTDL_EMERG, "citserver: Can't create a socket: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't create a socket: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); return(-1); } @@ -306,24 +308,32 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - lprintf(CTDL_EMERG, "citserver: Can't bind: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't bind: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); close(s); return(-1); } /* set to nonblock - we need this for some obscure situations */ if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) { - lprintf(CTDL_EMERG, - "citserver: Can't set socket to non-blocking: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't set socket to non-blocking: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); close(s); return(-1); } if (listen(s, actual_queue_len) < 0) { - lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't listen: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); close(s); return(-1); } @@ -336,7 +346,7 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len) /* * Create a Unix domain socket and listen on it */ -int ig_uds_server(char *sockpath, int queue_len) +int ig_uds_server(char *sockpath, int queue_len, char **errormessage) { struct sockaddr_un addr; int s; @@ -348,8 +358,10 @@ int ig_uds_server(char *sockpath, int queue_len) i = unlink(sockpath); if (i != 0) if (errno != ENOENT) { - lprintf(CTDL_EMERG, "citserver: can't unlink %s: %s\n", + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, "citserver: can't unlink %s: %s", sockpath, strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); return(-1); } @@ -359,29 +371,40 @@ int ig_uds_server(char *sockpath, int queue_len) s = socket(AF_UNIX, SOCK_STREAM, 0); if (s < 0) { - lprintf(CTDL_EMERG, "citserver: Can't create a socket: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't create a socket: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); return(-1); } if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - lprintf(CTDL_EMERG, "citserver: Can't bind: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't bind: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); return(-1); } /* set to nonblock - we need this for some obscure situations */ if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) { - lprintf(CTDL_EMERG, - "citserver: Can't set socket to non-blocking: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't set socket to non-blocking: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); close(s); return(-1); } if (listen(s, actual_queue_len) < 0) { - lprintf(CTDL_EMERG, "citserver: Can't listen: %s\n", - strerror(errno)); + *errormessage = (char*) malloc(SIZ + 1); + snprintf(*errormessage, SIZ, + "citserver: Can't listen: %s", + strerror(errno)); + lprintf(CTDL_EMERG, "%s\n", *errormessage); return(-1); } @@ -560,8 +583,10 @@ void client_write(char *buf, int nbytes) retval = write(CC->client_socket, &buf[bytes_written], nbytes - bytes_written); if (retval < 1) { - lprintf(CTDL_ERR, "client_write() failed: %s\n", - strerror(errno)); + lprintf(CTDL_ERR, + "client_write(%d bytes) failed: %s (%d)\n", + nbytes - bytes_written, + strerror(errno), errno); CC->kill_me = 1; return; } @@ -623,8 +648,7 @@ int client_read_to(char *buf, int bytes, int timeout) rlen = read(CC->client_socket, &buf[len], bytes-len); if (rlen<1) { - lprintf(CTDL_ERR, "client_read() failed: %s\n", - strerror(errno)); + /* The socket has been disconnected! */ CC->kill_me = 1; return(-1); } @@ -667,11 +691,12 @@ int client_getln(char *buf, int bufsize) while (buf[i] != '\n' && retval == 1) retval = client_read(&buf[i], 1); - /* Strip the trailing newline and any trailing nonprintables (cr's) + /* Strip the trailing LF, and the trailing CR if present. */ buf[i] = 0; - while ((strlen(buf)>0)&&(!isprint(buf[strlen(buf)-1]))) + while ( (strlen(buf) > 0) && ((buf[strlen(buf)-1]==10) || (buf[strlen(buf)-1] == 13)) ) { buf[strlen(buf)-1] = 0; + } if (retval < 0) safestrncpy(buf, "000", bufsize); return(retval); } @@ -815,8 +840,9 @@ void create_worker(void) { /* * Create the indexer thread and begin its operation. + * Then create the checkpoint thread and begin its operation. */ -void create_indexer_thread(void) { +void create_maintenance_threads(void) { int ret; pthread_attr_t attr; @@ -838,10 +864,12 @@ void create_indexer_thread(void) { return; } - if ((ret = pthread_create(&indexer_thread_tid, &attr, indexer_thread, NULL) != 0)) - { - lprintf(CTDL_ALERT, "Can't create indexer thread: %s\n", - strerror(ret)); + if ((ret = pthread_create(&indexer_thread_tid, &attr, indexer_thread, NULL) != 0)) { + lprintf(CTDL_ALERT, "Can't create thread: %s\n", strerror(ret)); + } + + if ((ret = pthread_create(&checkpoint_thread_tid, &attr, checkpoint_thread, NULL) != 0)) { + lprintf(CTDL_ALERT, "Can't create thread: %s\n", strerror(ret)); } pthread_attr_destroy(&attr); @@ -1049,19 +1077,29 @@ do_select: force_purge = 0; "New client socket %d\n", ssock); + /* The master socket is non-blocking but the client + * sockets need to be blocking, otherwise certain + * operations barf on FreeBSD. Not a fatal error. + */ + if (fcntl(ssock, F_SETFL, 0) < 0) { + lprintf(CTDL_EMERG, + "citserver: Can't set socket to blocking: %s\n", + strerror(errno)); + } + /* New context will be created already - * set up in the CON_EXECUTING state. - */ + * set up in the CON_EXECUTING state. + */ con = CreateNewContext(); - /* Assign new socket number to it. */ + /* Assign our new socket number to it. */ con->client_socket = ssock; con->h_command_function = serviceptr->h_command_function; con->h_async_function = serviceptr->h_async_function; - /* Determine whether local socket */ + /* Determine whether it's a local socket */ if (serviceptr->sockpath != NULL) con->is_local_socket = 1;