summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2012-03-09 09:57:41 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2012-03-09 09:57:41 +0000
commitdbaaf4ad89f61a154abf6b48600210ec50ecb62c (patch)
tree7be08af55151fda5b7fc271020a8c1a8e3172c21 /usr.bin
parent37f5922e0f5959725c6127adc2e3e3d73e7e8934 (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.c55
-rw-r--r--usr.bin/tmux/server.c8
-rw-r--r--usr.bin/tmux/tmux.h4
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 */