diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2012-03-09 09:57:41 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2012-03-09 09:57:41 +0000 |
commit | dbaaf4ad89f61a154abf6b48600210ec50ecb62c (patch) | |
tree | 7be08af55151fda5b7fc271020a8c1a8e3172c21 /usr.bin | |
parent | 37f5922e0f5959725c6127adc2e3e3d73e7e8934 (diff) |
Use a lock file and flock() to serialize server start, avoids problems
when running a bunch of tmux from cron at the same time. Based on a diff
from Tim Ruehsen.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/client.c | 55 | ||||
-rw-r--r-- | usr.bin/tmux/server.c | 8 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 4 |
3 files changed, 49 insertions, 18 deletions
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c index bd729b1f769..e48d33454c9 100644 --- a/usr.bin/tmux/client.c +++ b/usr.bin/tmux/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.48 2011/03/03 08:51:47 nicm Exp $ */ +/* $OpenBSD: client.c,v 1.49 2012/03/09 09:57:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -39,6 +39,7 @@ int client_exitval; enum msgtype client_exittype; int client_attached; +int client_get_lock(char *); int client_connect(char *, int); void client_send_identify(int); void client_send_environ(void); @@ -49,13 +50,38 @@ void client_callback(int, short, void *); int client_dispatch_attached(void); int client_dispatch_wait(void *); +/* + * Get server create lock. If already held then server start is happening in + * another client, so block until the lock is released and return -1 to + * retry. Ignore other errors - just continue and start the server without the + * lock. + */ +int +client_get_lock(char *lockfile) +{ + int lockfd; + + if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) + fatal("open failed"); + + if (flock(lockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) { + while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR) + /* nothing */; + close(lockfd); + return (-1); + } + + return (lockfd); +} + /* Connect client to server. */ int client_connect(char *path, int start_server) { struct sockaddr_un sa; size_t size; - int fd; + int fd, lockfd; + char *lockfile; memset(&sa, 0, sizeof sa); sa.sun_family = AF_UNIX; @@ -65,24 +91,25 @@ client_connect(char *path, int start_server) return (-1); } +retry: if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("socket failed"); if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) { - if (!start_server) + if (errno != ECONNREFUSED && errno != ENOENT) goto failed; - switch (errno) { - case ECONNREFUSED: - if (unlink(path) != 0) - goto failed; - /* FALLTHROUGH */ - case ENOENT: - if ((fd = server_start()) == -1) - goto failed; - break; - default: + if (!start_server) goto failed; - } + close(fd); + + xasprintf(&lockfile, "%s.lock", path); + if ((lockfd = client_get_lock(lockfile)) == -1) + goto retry; + if (unlink(path) != 0 && errno != ENOENT) + return (-1); + fd = server_start(lockfd, lockfile); + xfree(lockfile); + close(lockfd); } setblocking(fd, 0); diff --git a/usr.bin/tmux/server.c b/usr.bin/tmux/server.c index 876fe320f15..e990955ce72 100644 --- a/usr.bin/tmux/server.c +++ b/usr.bin/tmux/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.102 2011/03/27 20:27:26 nicm Exp $ */ +/* $OpenBSD: server.c,v 1.103 2012/03/09 09:57:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -104,7 +104,7 @@ server_create_socket(void) /* Fork new server. */ int -server_start(void) +server_start(int lockfd, char *lockfile) { struct window_pane *wp; int pair[2]; @@ -161,6 +161,10 @@ server_start(void) server_fd = server_create_socket(); server_client_create(pair[1]); + unlink(lockfile); + xfree(lockfile); + close(lockfd); + if (access(SYSTEM_CFG, R_OK) == 0) load_cfg(SYSTEM_CFG, NULL, &cfg_causes); else if (errno != ENOENT) { diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 099ac755b3d..571a9fce4e2 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.318 2012/03/04 07:38:11 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.319 2012/03/09 09:57:40 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1687,7 +1687,7 @@ const char *key_string_lookup_key(int); extern struct clients clients; extern struct clients dead_clients; extern struct paste_stack global_buffers; -int server_start(void); +int server_start(int, char *); void server_update_socket(void); /* server-client.c */ |