Revision: 2722
          http://tmux.svn.sourceforge.net/tmux/?rev=2722&view=rev
Author:   tcunha
Date:     2012-03-18 01:28:10 +0000 (Sun, 18 Mar 2012)
Log Message:
-----------
Sync OpenBSD patchset 1043:

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.

Modified Paths:
--------------
    trunk/client.c
    trunk/server.c
    trunk/tmux.h

Modified: trunk/client.c
===================================================================
--- trunk/client.c      2012-03-16 21:10:39 UTC (rev 2721)
+++ trunk/client.c      2012-03-18 01:28:10 UTC (rev 2722)
@@ -39,6 +39,7 @@
 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 @@
 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 @@
                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 (errno != ECONNREFUSED && errno != ENOENT)
+                       goto failed;
                if (!start_server)
                        goto failed;
-               switch (errno) {
-               case ECONNREFUSED:
-                       if (unlink(path) != 0)
-                               goto failed;
-                       /* FALLTHROUGH */
-               case ENOENT:
-                       if ((fd = server_start()) == -1)
-                               goto failed;
-                       break;
-               default:
-                       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);

Modified: trunk/server.c
===================================================================
--- trunk/server.c      2012-03-16 21:10:39 UTC (rev 2721)
+++ trunk/server.c      2012-03-18 01:28:10 UTC (rev 2722)
@@ -103,7 +103,7 @@
 
 /* Fork new server. */
 int
-server_start(void)
+server_start(int lockfd, char *lockfile)
 {
        struct window_pane      *wp;
        int                      pair[2];
@@ -162,6 +162,10 @@
        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) {

Modified: trunk/tmux.h
===================================================================
--- trunk/tmux.h        2012-03-16 21:10:39 UTC (rev 2721)
+++ trunk/tmux.h        2012-03-18 01:28:10 UTC (rev 2722)
@@ -1683,7 +1683,7 @@
 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 */

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here 
http://p.sf.net/sfu/sfd2d-msazure
_______________________________________________
tmux-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tmux-cvs

Reply via email to