aboutsummaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/src/server.c b/src/server.c
index 6e8dba2..6d90c61 100644
--- a/src/server.c
+++ b/src/server.c
@@ -255,10 +255,34 @@ static void new_connection_cb(EV_P_ ev_io *w, int revents)
int readpipe[2]; /* child->parent */
int outpipe [2]; /* parent->child */
- if(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, readpipe) < 0)
- error("error creating pipe, need linux kernel >= 3.4");
- if(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, outpipe) < 0)
- error("error creating pipe, need linux kernel >= 3.4");
+ /* try several methods to create a packet pipe between the child and master: */
+
+ /* first try creating a pipe in "packet mode": see pipe(2) */
+ if(pipe2(readpipe, O_DIRECT) < 0)
+ {
+ /* then try a SOCK_SEQPACKET socket pair: see unix(7) */
+ if(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, readpipe) < 0)
+ {
+ /* if that failed, try a SOCK_DGRAM socket as a last resort */
+ if(socketpair(AF_UNIX, SOCK_DGRAM, 0, readpipe) < 0)
+ error("couldn't create child-master communication pipe");
+ else
+ debugf("WARNING: Using a SOCK_DGRAM socket pair for IPC, performance may be degraded.\n");
+ }
+ else
+ debugf("Using a SOCK_SEQPACKET socket pair for IPC.\n");
+ }
+ else
+ debugf("Using a packet-mode pipe for IPC.\n");
+
+ if(pipe2(outpipe, O_DIRECT) < 0)
+ {
+ if(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, outpipe) < 0)
+ {
+ if(socketpair(AF_UNIX, SOCK_DGRAM, 0, outpipe) < 0)
+ error("error creating pipe, need linux kernel >= 3.4");
+ }
+ }
pid_t pid = fork();
if(pid < 0)
@@ -329,6 +353,7 @@ static void init_signals(void)
{
struct sigaction sa;
+ /* SIGINT and SIGTERM cause graceful shutdown */
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGINT);
sa.sa_handler = sigint_handler;
@@ -338,6 +363,7 @@ static void init_signals(void)
if(sigaction(SIGTERM, &sa, NULL) < 0)
error("sigaction");
+ /* ignore SIGPIPE */
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
@@ -345,7 +371,7 @@ static void init_signals(void)
error("sigaction");
/* libev's default SIGCHLD handler exhibits some really strange
- * behavior, which we don't like, so we use our own ;) */
+ * behavior, which we don't like, so we use our own */
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGCHLD);
sa.sa_handler = sigchld_handler;
@@ -367,7 +393,7 @@ static void parse_args(int argc, char *argv[])
switch(c)
{
case 'h': /* help */
- debugf("FIXME: usage message");
+ debugf("Usage: %s [-d PREFIX] [-a <username> <password>]\n", argv[0]);
exit(0);
case 'a': /* automatic first-run config */
autoconfig = true;
@@ -393,7 +419,7 @@ static SIMP_EQUAL(pid_t, pid_equal);
static void check_libs(void)
{
- debugf("*** Starting NetCosm %s (libev %d.%d, %s) ***\n",
+ debugf("*** NetCosm %s (libev %d.%d, %s) ***\n",
NETCOSM_VERSION, EV_VERSION_MAJOR, EV_VERSION_MINOR, OPENSSL_VERSION_TEXT);
assert(ev_version_major() == EV_VERSION_MAJOR &&
ev_version_minor() >= EV_VERSION_MINOR);
@@ -405,11 +431,9 @@ int server_main(int argc, char *argv[])
parse_args(argc, argv);
- server_socket = server_bind();
-
userdb_init(USERFILE);
-
- /* also perform first-time setup */
+
+ /* also performs first-time setup: */
check_userfile();
load_worldfile();
@@ -427,10 +451,12 @@ int server_main(int argc, char *argv[])
debugf("Listening on port %d\n", port);
+ server_socket = server_bind();
+
struct ev_loop *loop = ev_default_loop(0);
/* we initialize signals after creating the default event loop
- * because libev grabs SIGCHLD */
+ * because libev grabs SIGCHLD in the process */
init_signals();
ev_io server_watcher;