--- /dev/null
+/*
+ * $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 <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <syslog.h>
+#include <sys/syslog.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include <limits.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/un.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <grp.h>
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#include "webcit.h"
+#include "sysdep.h"
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#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<MAX_SEMAPHORES; ++i) {
+ pthread_mutex_init(&Critters[i], NULL);
+ }
+}
+
+/*
+ * Obtain a semaphore lock to begin a critical section.
+ */
+void begin_critical_section(int which_one)
+{
+ /* lprintf(CTDL_DEBUG, "begin_critical_section(%d)\n", which_one); */
+ pthread_mutex_lock(&Critters[which_one]);
+}
+
+/*
+ * Release a semaphore lock to end a critical section.
+ */
+void end_critical_section(int which_one)
+{
+ pthread_mutex_unlock(&Critters[which_one]);
+}
+
#include "sysdep.h"
+
+#include <sys/select.h>
+
#include <ctype.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
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, '|')
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,
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);
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);
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);
}
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();
}
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) {
start_daemon(pidfile);
}
else {
- signal(SIGTERM, graceful_shutdown);
+/// signal(SIGTERM, graceful_shutdown);
+ signal(SIGHUP, graceful_shutdown);
}
/** Tell 'em who's in da house */
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.
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,
} while (!time_to_die);
- lprintf (1, "bye");
+ lprintf (1, "bye\n");
pthread_exit(NULL);
}