diff options
Diffstat (limited to 'src/server.c')
| -rw-r--r-- | src/server.c | 50 |
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; |