mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 13:37:12 +00:00
Sync OpenBSD patchset 225:
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.
This commit is contained in:
87
server.c
87
server.c
@ -1,4 +1,4 @@
|
||||
/* $Id: server.c,v 1.164 2009-07-28 23:11:18 tcunha Exp $ */
|
||||
/* $Id: server.c,v 1.165 2009-08-09 17:19:18 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@ -130,10 +130,11 @@ server_client_index(struct client *c)
|
||||
int
|
||||
server_start(char *path)
|
||||
{
|
||||
int pair[2], srv_fd, null_fd;
|
||||
char *cause;
|
||||
struct client *c;
|
||||
int pair[2], srv_fd;
|
||||
char *cause;
|
||||
#ifdef HAVE_SETPROCTITLE
|
||||
char rpathbuf[MAXPATHLEN];
|
||||
char rpathbuf[MAXPATHLEN];
|
||||
#endif
|
||||
|
||||
/* The first client is special and gets a socketpair; create it. */
|
||||
@ -155,9 +156,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);
|
||||
@ -172,47 +176,39 @@ server_start(char *path)
|
||||
start_time = time(NULL);
|
||||
socket_path = path;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (cfg_file != NULL && load_cfg(cfg_file, &cause) != 0) {
|
||||
log_warnx("%s", cause);
|
||||
exit(1);
|
||||
}
|
||||
logfile("server");
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
log_debug("server started, pid %ld", (long) getpid());
|
||||
log_debug("socket path %s", socket_path);
|
||||
|
||||
#ifdef HAVE_SETPROCTITLE
|
||||
if (realpath(socket_path, rpathbuf) == NULL)
|
||||
strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
|
||||
log_debug("socket path %s", socket_path);
|
||||
setproctitle("server (%s)", rpathbuf);
|
||||
#endif
|
||||
|
||||
srv_fd = server_create_socket();
|
||||
server_create_client(pair[1]);
|
||||
|
||||
if (access(SYSTEM_CFG, R_OK) != 0) {
|
||||
if (errno != ENOENT) {
|
||||
xasprintf(
|
||||
&cause, "%s: %s", strerror(errno), SYSTEM_CFG);
|
||||
goto error;
|
||||
}
|
||||
} else if (load_cfg(SYSTEM_CFG, &cause) != 0)
|
||||
goto error;
|
||||
if (cfg_file != NULL && load_cfg(cfg_file, &cause) != 0)
|
||||
goto error;
|
||||
|
||||
exit(server_main(srv_fd));
|
||||
|
||||
error:
|
||||
/* Write the error and shutdown the server. */
|
||||
c = ARRAY_FIRST(&clients);
|
||||
|
||||
server_write_error(c, cause);
|
||||
xfree(cause);
|
||||
|
||||
server_shutdown();
|
||||
c->flags |= CLIENT_BAD;
|
||||
|
||||
exit(server_main(srv_fd));
|
||||
}
|
||||
|
||||
@ -424,8 +420,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -677,7 +678,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;
|
||||
}
|
||||
@ -725,6 +727,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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user