about summary refs log tree commit diff
path: root/src/daemontools-extras/s6-setlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemontools-extras/s6-setlock.c')
-rw-r--r--src/daemontools-extras/s6-setlock.c87
1 files changed, 50 insertions, 37 deletions
diff --git a/src/daemontools-extras/s6-setlock.c b/src/daemontools-extras/s6-setlock.c
index fea6a11..673caaf 100644
--- a/src/daemontools-extras/s6-setlock.c
+++ b/src/daemontools-extras/s6-setlock.c
@@ -4,30 +4,40 @@
 #include <errno.h>
 #include <signal.h>
 
-#include <skalibs/allreadwrite.h>
 #include <skalibs/sgetopt.h>
 #include <skalibs/strerr.h>
 #include <skalibs/types.h>
 #include <skalibs/tai.h>
-#include <skalibs/iopause.h>
-#include <skalibs/cspawn.h>
+#include <skalibs/sig.h>
+#include <skalibs/alarm.h>
 #include <skalibs/djbunix.h>
 #include <skalibs/exec.h>
 
 #include <s6/config.h>
-#include "s6lockd.h"
 
-#define USAGE "s6-setlock [ -r | -w ] [ -n | -N | -t timeout ] lockfile prog..."
+#define USAGE "s6-setlock [ -r | -w ] [ -n | -N ] [ -t timeout ] [ -d fd ] lockfile prog..."
 #define dieusage() strerr_dieusage(100, USAGE)
 
+static char const *file ;
+
+static void sigalrm_handler (int sig)
+{
+  (void)sig ;
+  strerr_dief3x(1, "lock ", file, ": timed out") ;
+}
+
 int main (int argc, char const *const *argv)
 {
   unsigned int nb = 0, ex = 1 ;
   unsigned int timeout = 0 ;
+  int dest = -1 ;
+  int fd ;
+  int r ;
   PROG = "s6-setlock" ;
+  
   for (;;)
   {
-    int opt = lgetopt(argc, argv, "nNrwt:") ;
+    int opt = lgetopt(argc, argv, "nNrwt:d:") ;
     if (opt == -1) break ;
     switch (opt)
     {
@@ -35,47 +45,50 @@ int main (int argc, char const *const *argv)
       case 'N' : nb = 0 ; break ;
       case 'r' : ex = 0 ; break ;
       case 'w' : ex = 1 ; break ;
-      case 't' : if (!uint0_scan(subgetopt_here.arg, &timeout)) dieusage() ; nb = 2 ; break ;
+      case 't' : if (!uint0_scan(subgetopt_here.arg, &timeout)) dieusage() ; break ;
+      case 'd' : { unsigned int u ; if (!uint0_scan(subgetopt_here.arg, &u)) dieusage() ; dest = u ; break ; }
       default : dieusage() ;
     }
   }
   argc -= subgetopt_here.ind ; argv += subgetopt_here.ind ;
   if (argc < 2) dieusage() ;
+  file = argv[0] ;
 
-  if (nb < 2) s6lockd_openandlock(argv[0], ex, nb) ;
+  if (ex)
+  {
+    fd = open_create(file) ;
+    if (fd == -1) strerr_diefu3sys(111, "open ", file, " for writing") ;
+  }
   else
   {
-    char const *cargv[4] = { "s6lockd-helper", ex ? "w" : "r", argv[0], 0 } ;
-    char const *nullenv = { 0 } ;
-    iopause_fd x = { .events = IOPAUSE_READ } ;
-    tain deadline ;
-    int p[2] = { 0, 1 } ;
-    pid_t pid ;
-    char c ;
-    tain_now_set_stopwatch_g() ;
-    tain_from_millisecs(&deadline, timeout) ;
-    tain_add_g(&deadline, &deadline) ;
-    pid = child_spawn2(S6_LIBEXECPREFIX "s6lockd-helper", cargv, &nullenv, p) ;
-    if (!pid) strerr_diefu2sys(111, "spawn ", S6_LIBEXECPREFIX "s6lockd-helper") ;
-    x.fd = p[0] ;
-    for (;;)
+    fd = open_read(file) ;
+    if (fd == -1)
     {
-      ssize_t rr ;
-      int r = iopause_g(&x, 1, &deadline) ;
-      if (r < 0) strerr_diefu1sys(111, "iopause") ;
-      if (!r)
-      {
-        kill(pid, SIGTERM) ;
-        errno = ETIMEDOUT ;
-        strerr_diefu1sys(1, "acquire lock") ;
-      }
-      rr = sanitize_read(fd_read(p[0], &c, 1)) ;
-      if (rr < 0) strerr_diefu1sys(111, "read ack from helper") ;
-      if (rr) break ;
+      if (errno != ENOENT) strerr_diefu3sys(111, "open ", file, " for reading") ;
+      fd = open_create(file) ;
+      if (fd == -1) strerr_diefu2sys(111, "create ", file) ;
+      fd_close(fd) ;
+      fd = open_read(file) ;
+      if (fd == -1) strerr_diefu3sys(111, "open ", file, " for reading") ;
     }
-    if (c != '!') strerr_dief1x(111, "helper sent garbage ack") ;
-    fd_close(p[0]) ;
-    if (uncoe(p[1]) < 0) strerr_diefu1sys(111, "uncoe fd to helper") ;
   }
+
+  if (timeout)
+  {
+    tain tto ;
+    tain_from_millisecs(&tto, timeout) ;
+    if (!sig_catch(SIGALRM, &sigalrm_handler))
+      strerr_diefu1sys(111, "set SIGALRM handler") ;
+    if (!alarm_timeout(&tto))
+      strerr_diefu1sys(111, "set timer") ;
+  }
+  r = fd_lock(fd, ex, nb) ;
+  if (timeout) alarm_disable() ;
+
+  if (!r) errno = EBUSY ;
+  if (r < 1) strerr_diefu2sys(1, "lock ", file) ;
+
+  if (dest >= 0 && fd_move(dest, fd) == -1)
+    strerr_diefu1sys(111, "move lock descriptor") ;
   xexec(argv+1) ;
 }