aboutsummaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-08-07 15:39:10 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-08-07 15:39:10 +0000
commite89e70e71575417195285a3ea55c430654f9fc21 (patch)
tree7b2693e599d1137fa818a6ec8330a299de536c4d /server.c
parentccaf8724e4c5f1909c8eaf62963ded1265a271b2 (diff)
downloadrtmux-e89e70e71575417195285a3ea55c430654f9fc21.tar.gz
rtmux-e89e70e71575417195285a3ea55c430654f9fc21.tar.bz2
rtmux-e89e70e71575417195285a3ea55c430654f9fc21.zip
If there is an error in the configuration file, don't just exit(1) as this can
cause the client to hang. Instead, send the error message, then mark the client as bad and start a normal shutdown so the server exits once the error is written. This also allows some code duplicating daemon(3) to be trimmed and logging to begin earlier. Prompted by Theo noticing the behaviour on error wasn't documented.
Diffstat (limited to 'server.c')
-rw-r--r--server.c83
1 files changed, 45 insertions, 38 deletions
diff --git a/server.c b/server.c
index 668a8251..927cfeb6 100644
--- a/server.c
+++ b/server.c
@@ -131,9 +131,10 @@ server_client_index(struct client *c)
int
server_start(char *path)
{
- int pair[2], srv_fd, null_fd;
- char *cause;
- char rpathbuf[MAXPATHLEN];
+ struct client *c;
+ int pair[2], srv_fd;
+ char *cause;
+ char rpathbuf[MAXPATHLEN];
/* The first client is special and gets a socketpair; create it. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
@@ -154,9 +155,12 @@ server_start(char *path)
* Must daemonise before loading configuration as the PID changes so
* $TMUX would be wrong for sessions created in the config file.
*/
- if (daemon(1, 1) != 0)
+ if (daemon(1, 0) != 0)
fatal("daemon failed");
+ logfile("server");
+ log_debug("server started, pid %ld", (long) getpid());
+
ARRAY_INIT(&windows);
ARRAY_INIT(&clients);
ARRAY_INIT(&sessions);
@@ -171,44 +175,36 @@ server_start(char *path)
start_time = time(NULL);
socket_path = path;
+ if (realpath(socket_path, rpathbuf) == NULL)
+ strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
+ log_debug("socket path %s", socket_path);
+ setproctitle("server (%s)", rpathbuf);
+
+ srv_fd = server_create_socket();
+ server_create_client(pair[1]);
+
if (access(SYSTEM_CFG, R_OK) != 0) {
if (errno != ENOENT) {
- log_warn("%s", SYSTEM_CFG);
- exit(1);
- }
- } else {
- if (load_cfg(SYSTEM_CFG, &cause) != 0) {
- log_warnx("%s", cause);
- exit(1);
+ xasprintf(
+ &cause, "%s: %s", strerror(errno), SYSTEM_CFG);
+ goto error;
}
- }
- if (cfg_file != NULL && load_cfg(cfg_file, &cause) != 0) {
- log_warnx("%s", cause);
- exit(1);
- }
- logfile("server");
+ } else if (load_cfg(SYSTEM_CFG, &cause) != 0)
+ goto error;
+ if (cfg_file != NULL && load_cfg(cfg_file, &cause) != 0)
+ goto error;
- /*
- * Close stdin/stdout/stderr. Can't let daemon() do this as they are
- * needed until now to print configuration file errors.
- */
- if ((null_fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
- dup2(null_fd, STDIN_FILENO);
- dup2(null_fd, STDOUT_FILENO);
- dup2(null_fd, STDERR_FILENO);
- if (null_fd > 2)
- close(null_fd);
- }
+ exit(server_main(srv_fd));
- log_debug("server started, pid %ld", (long) getpid());
- log_debug("socket path %s", socket_path);
+error:
+ /* Write the error and shutdown the server. */
+ c = ARRAY_FIRST(&clients);
- if (realpath(socket_path, rpathbuf) == NULL)
- strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
- setproctitle("server (%s)", rpathbuf);
+ server_write_error(c, cause);
+ xfree(cause);
- srv_fd = server_create_socket();
- server_create_client(pair[1]);
+ server_shutdown();
+ c->flags |= CLIENT_BAD;
exit(server_main(srv_fd));
}
@@ -419,8 +415,13 @@ server_shutdown(void)
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
- if (c != NULL)
- server_write_client(c, MSG_SHUTDOWN, NULL, 0);
+ if (c != NULL) {
+ if (c->flags & CLIENT_BAD)
+ server_lost_client(c);
+ else
+ server_write_client(c, MSG_SHUTDOWN, NULL, 0);
+ c->flags |= CLIENT_BAD;
+ }
}
}
@@ -672,7 +673,8 @@ server_fill_clients(struct pollfd **pfd)
(*pfd)->fd = -1;
else {
(*pfd)->fd = c->fd;
- (*pfd)->events = POLLIN;
+ if (!(c->flags & CLIENT_BAD))
+ (*pfd)->events = POLLIN;
if (BUFFER_USED(c->out) > 0)
(*pfd)->events |= POLLOUT;
}
@@ -720,6 +722,11 @@ server_handle_clients(struct pollfd **pfd)
server_lost_client(c);
(*pfd) += 2;
continue;
+ } else if (c->flags & CLIENT_BAD) {
+ if (BUFFER_USED(c->out) == 0)
+ server_lost_client(c);
+ (*pfd) += 2;
+ continue;
} else
server_msg_dispatch(c);
}