diff options
Diffstat (limited to 'src/daemontools-extras/s6-setlock.c')
-rw-r--r-- | src/daemontools-extras/s6-setlock.c | 87 |
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) ; } |