From 41dec6436242c4daccdd9fdee3ac052004c439bd Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Mon, 16 Mar 2026 21:09:38 +0000
Subject: Refactor ftrig using sass; clean up API a bit, update its users
---
src/supervision/s6-notifyoncheck.c | 210 +++++++++++++++++++++++--------------
src/supervision/s6-svlisten.c | 10 +-
src/supervision/s6-svlisten.h | 6 +-
src/supervision/s6-svlisten1.c | 10 +-
src/supervision/s6-svscan.c | 156 +++++++++++++++------------
src/supervision/s6-svwait.c | 5 +-
src/supervision/s6_svlisten_loop.c | 35 ++++---
7 files changed, 253 insertions(+), 179 deletions(-)
(limited to 'src/supervision')
diff --git a/src/supervision/s6-notifyoncheck.c b/src/supervision/s6-notifyoncheck.c
index 8c139af..f86b1e0 100644
--- a/src/supervision/s6-notifyoncheck.c
+++ b/src/supervision/s6-notifyoncheck.c
@@ -7,10 +7,11 @@
#include
#include
+#include
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -23,15 +24,31 @@
#ifdef S6_USE_EXECLINE
#include
-#define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] [ -c \"checkprog...\" ] prog..."
-#define OPTIONS "d3:s:T:t:w:n:c:"
+# define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] [ -c \"checkprog...\" ] prog..."
#else
-#define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] prog..."
-#define OPTIONS "d3:s:T:t:w:n:"
+# define USAGE "s6-notifyoncheck [ -d ] [ -3 fd ] [ -s initialsleep ] [ -T globaltimeout ] [ -t localtimeout ] [ -w waitingtime ] [ -n tries ] prog..."
#endif
#define dieusage() strerr_dieusage(100, USAGE)
+enum golb_e
+{
+ GOLB_DOUBLEFORK = 0x01,
+} ;
+
+enum gola_e
+{
+ GOLA_NOTIF,
+ GOLA_INITIALSLEEP,
+ GOLA_GLOBALTIMEOUT,
+ GOLA_LOCALTIMEOUT,
+ GOLA_WAITINGTIME,
+ GOLA_TRIES,
+#ifdef S6_USE_EXECLINE
+ GOLA_CHECKPROG,
+#endif
+ GOLA_N
+} ;
static inline int read_uint (char const *file, unsigned int *fd)
{
@@ -65,97 +82,128 @@ static inline int handle_signals (pid_t pid, int *w)
}
}
-static int handle_event (ftrigr_t *a, uint16_t id, pid_t pid)
+static int handle_event (ftrigr *a, uint32_t id, pid_t pid)
{
int r ;
- char what ;
- if (ftrigr_update(a) < 0) strerr_diefu1sys(111, "ftrigr_update") ;
- r = ftrigr_check(a, id, &what) ;
- if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ;
- if (r && what == 'd')
+ struct iovec v ;
+ if (ftrigr_update(a) == -1) strerr_diefu1sys(111, "ftrigr_update") ;
+ r = ftrigr_peek(a, id, &v) ;
+ if (r == -1) strerr_diefu1sys(111, "ftrigr_check") ;
+ if (r)
{
- if (pid) kill(pid, SIGTERM) ;
- return 1 ;
+ if (memchr(v.iov_base, 'd', v.iov_len))
+ {
+ if (pid) kill(pid, SIGTERM) ;
+ ftrigr_ack(a, id) ;
+ return 1 ;
+ }
+ ftrigr_ack(a, id) ;
}
return 0 ;
}
-int main (int argc, char const *const *argv, char const *const *envp)
+int main (int argc, char const *const *argv)
{
- ftrigr_t a = FTRIGR_ZERO ;
- iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .events = IOPAUSE_READ } } ;
- char const *childargv[4] = { "./data/check", 0, 0, 0 } ;
+ static gol_bool rgolb[] =
+ {
+ { .so = 'd', .lo = "doublefork", .clear = 0, .set = GOLB_DOUBLEFORK },
+ } ;
+ static gol_arg rgola[] =
+ {
+ { .so = '3', .lo = "notification-fd", .i = GOLA_NOTIF },
+ { .so = 's', .lo = "initial-sleep", .i = GOLA_INITIALSLEEP },
+ { .so = 'T', .lo = "global-timeout", .i = GOLA_GLOBALTIMEOUT },
+ { .so = 't', .lo = "local-timeout", .i = GOLA_LOCALTIMEOUT },
+ { .so = 'w', .lo = "waiting-time", .i = GOLA_WAITINGTIME },
+ { .so = 'n', .lo = "tries", .i = GOLA_TRIES },
#ifdef S6_USE_EXECLINE
- char const *checkprog = 0 ;
+ { .so = 'c', .lo = "check-program", .i = GOLA_CHECKPROG },
#endif
+ } ;
+ uint64_t wgolb = 0 ;
+ char const *wgola[GOLA_N] = { 0 } ;
+ ftrigr a = FTRIGR_ZERO ;
+ iopause_fd x[2] = { { .events = IOPAUSE_READ }, { .events = IOPAUSE_READ } } ;
+ char const *childargv[4] = { "./data/check", 0, 0, 0 } ;
unsigned int fd ;
- int df = 0 ;
- int autodetect = 1 ;
int p[2] ;
- tain globaldeadline, sleeptto, localtto, waittto ;
- unsigned int tries = 7 ;
- uint16_t id ;
+ tain sleeptto ;
+ tain globaldeadline = TAIN_INFINITE_RELATIVE ;
+ tain localtto = TAIN_INFINITE_RELATIVE ;
+ tain waittto = TAIN_INFINITE_RELATIVE ;
+ unsigned int tries ;
+ uint32_t id ;
+ unsigned int golc ;
+
PROG = "s6-notifyoncheck" ;
+ golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ;
+ argc -= golc ; argv += golc ;
+ if (!argc) dieusage() ;
+ if (wgola[GOLA_NOTIF])
{
- subgetopt l = SUBGETOPT_ZERO ;
- unsigned int initialsleep = 10, globaltimeout = 0, localtimeout = 0, waitingtime = 1000 ;
- for (;;)
- {
- int opt = subgetopt_r(argc, argv, OPTIONS, &l) ;
- if (opt == -1) break ;
- switch (opt)
- {
- case 'd' : df = 1 ; break ;
- case '3' : if (!uint0_scan(l.arg, &fd)) dieusage() ; autodetect = 0 ; break ;
- case 's' : if (!uint0_scan(l.arg, &initialsleep)) dieusage() ; break ;
- case 'T' : if (!uint0_scan(l.arg, &globaltimeout)) dieusage() ; break ;
- case 't' : if (!uint0_scan(l.arg, &localtimeout)) dieusage() ; break ;
- case 'w' : if (!uint0_scan(l.arg, &waitingtime)) dieusage() ; break ;
- case 'n' : if (!uint0_scan(l.arg, &tries)) dieusage() ; break ;
-#ifdef S6_USE_EXECLINE
- case 'c' : checkprog = l.arg ; break ;
-#endif
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- if (!argc) dieusage() ;
-
- if (!tain_from_millisecs(&sleeptto, initialsleep)) dieusage() ;
- if (globaltimeout) tain_from_millisecs(&globaldeadline, globaltimeout) ;
- else globaldeadline = tain_infinite_relative ;
- if (localtimeout) tain_from_millisecs(&localtto, localtimeout) ;
- else localtto = tain_infinite_relative ;
- if (waitingtime) tain_from_millisecs(&waittto, waitingtime) ;
- else waittto = tain_infinite_relative ;
- if (!tries) tries = UINT_MAX ;
+ if (!uint0_scan(wgola[GOLA_NOTIF], &fd))
+ strerr_dief2x(100, "notification-fd", " must be an unsigned integer") ;
+ }
+ else
+ {
+ int r = read_uint("notification-fd", &fd) ;
+ if (r < 0) strerr_diefu2sys(111, "read ", "./notification-fd") ;
+ if (!r) strerr_dief2x(100, "invalid ", "./notification-fd") ;
}
+ if (fcntl(fd, F_GETFD) < 0)
+ strerr_dief2sys(111, "notification-fd", " sanity check failed") ;
+ if (wgola[GOLA_INITIALSLEEP])
+ {
+ if (!uint0_scan(wgola[GOLA_INITIALSLEEP], &tries))
+ strerr_dief2x(100, "initial-sleep", " must be an unsigned integer") ;
+ }
+ else tries = 10 ;
+ if (!tain_from_millisecs(&sleeptto, tries)) dieusage() ;
+ if (wgola[GOLA_GLOBALTIMEOUT])
{
- int r = s6_svc_ok(".") ;
- if (r < 0) strerr_diefu1sys(111, "sanity-check current service directory") ;
- if (!r) strerr_dief1x(100, "s6-supervise not running.") ;
+ if (!uint0_scan(wgola[GOLA_GLOBALTIMEOUT], &tries))
+ strerr_dief2x(100, "global-timeout", " must be an unsigned integer") ;
+ if (tries) tain_from_millisecs(&globaldeadline, tries) ;
+ }
+ if (wgola[GOLA_LOCALTIMEOUT])
+ {
+ if (!uint0_scan(wgola[GOLA_LOCALTIMEOUT], &tries))
+ strerr_dief2x(100, "local-timeout", " must be an unsigned integer") ;
+ if (tries) tain_from_millisecs(&localtto, tries) ;
+ }
+ if (wgola[GOLA_WAITINGTIME])
+ {
+ if (!uint0_scan(wgola[GOLA_WAITINGTIME], &tries))
+ strerr_dief2x(100, "waiting-time", " must be an unsigned integer") ;
}
+ else tries = 1000 ;
+ if (!tain_from_millisecs(&waittto, tries)) dieusage() ;
+ if (wgola[GOLA_TRIES])
+ {
+ if (!uint0_scan(wgola[GOLA_TRIES], &tries))
+ strerr_dief2x(100, "waiting-time", " must be an unsigned integer") ;
+ if (!tries) tries = UINT_MAX ;
+ }
+ else tries = 7 ;
+
#ifdef S6_USE_EXECLINE
- if (checkprog)
+ if (wgola[GOLA_CHECKPROG])
{
childargv[0] = EXECLINE_EXTBINPREFIX "execlineb" ;
childargv[1] = "-Pc" ;
- childargv[2] = checkprog ;
+ childargv[2] = wgola[GOLA_CHECKPROG] ;
}
#endif
- if (autodetect)
{
- int r = read_uint("notification-fd", &fd) ;
- if (r < 0) strerr_diefu2sys(111, "read ", "./notification-fd") ;
- if (!r) strerr_dief2x(100, "invalid ", "./notification-fd") ;
+ int r = s6_svc_ok(".") ;
+ if (r < 0) strerr_diefu1sys(111, "sanity-check current service directory") ;
+ if (!r) strerr_dief1x(100, "s6-supervise not running.") ;
}
- if (fcntl(fd, F_GETFD) < 0)
- strerr_dief2sys(111, "notification-fd", " sanity check failed") ;
- tain_now_set_stopwatch_g() ;
+ if (!tain_now_set_stopwatch_g()) strerr_diefu1sys(111, "tain_now") ;
tain_add_g(&globaldeadline, &globaldeadline) ;
@@ -179,16 +227,16 @@ int main (int argc, char const *const *argv, char const *const *envp)
*/
if (pipecoe(p) < 0) strerr_diefu1sys(111, "pipe") ;
- switch (df ? doublefork() : fork())
+ switch (wgolb & GOLB_DOUBLEFORK ? doublefork() : fork())
{
- case -1: strerr_diefu1sys(111, df ? "doublefork" : "fork") ;
+ case -1 : strerr_diefu1sys(111, wgolb & GOLB_DOUBLEFORK ? "doublefork" : "fork") ;
case 0 : break ;
default:
{
char c ;
- close((int)fd) ;
+ close(fd) ;
if (read(p[0], &c, 1) < 1) strerr_diefu1x(111, "synchronize with child") ;
- xexec_e(argv, envp) ;
+ xexec(argv) ;
}
}
@@ -197,11 +245,11 @@ int main (int argc, char const *const *argv, char const *const *envp)
close(p[0]) ;
if (!ftrigr_startf_g(&a, &globaldeadline))
strerr_diefu1sys(111, "ftrigr_startf") ;
- id = ftrigr_subscribe_g(&a, "event", "d", 0, &globaldeadline) ;
- if (!id) strerr_diefu1sys(111, "ftrigr_subscribe to event fifodir") ;
+ if (!ftrigr_subscribe_g(&a, &id, 0, 0, "event", "d", &globaldeadline))
+ strerr_diefu1sys(111, "ftrigr_subscribe to event fifodir") ;
x[0].fd = selfpipe_init() ;
- if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ;
+ if (x[0].fd == -1) strerr_diefu1sys(111, "selfpipe_init") ;
if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "trap SIGCHLD") ;
x[1].fd = ftrigr_fd(&a) ;
@@ -225,13 +273,13 @@ int main (int argc, char const *const *argv, char const *const *envp)
if (r < 0) strerr_diefu1sys(111, "iopause") ;
if (!r)
{
- if (!tain_future(&globaldeadline)) return 3 ;
+ if (!tain_future(&globaldeadline)) _exit(3) ;
else break ;
}
- if (handle_event(&a, id, 0)) return 2 ;
+ if (handle_event(&a, id, 0)) _exit(2) ;
}
- pid = cspawn(childargv[0], childargv, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
+ pid = cspawn(childargv[0], childargv, (char const *const *)environ, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
if (!pid)
{
strerr_warnwu2sys("spawn ", childargv[0]) ;
@@ -249,7 +297,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
if (!tain_future(&globaldeadline))
{
kill(pid, SIGTERM) ;
- return 3 ;
+ _exit(3) ;
}
else break ;
}
@@ -261,14 +309,14 @@ int main (int argc, char const *const *argv, char const *const *envp)
if (WIFEXITED(wstat) && !WEXITSTATUS(wstat))
{
fd_write((int)fd, "\n", 1) ;
- return 0 ;
+ _exit(0) ;
}
else break ;
}
}
- if (x[1].revents & IOPAUSE_READ && handle_event(&a, id, pid)) return 2 ;
+ if (x[1].revents & IOPAUSE_READ && handle_event(&a, id, pid)) _exit(2) ;
}
}
- return 1 ;
+ _exit(1) ;
}
diff --git a/src/supervision/s6-svlisten.c b/src/supervision/s6-svlisten.c
index 0774ef2..f2d5ddf 100644
--- a/src/supervision/s6-svlisten.c
+++ b/src/supervision/s6-svlisten.c
@@ -1,7 +1,9 @@
/* ISC license. */
#include
+#include
+#include
#include
#include
#include
@@ -17,7 +19,7 @@
#define USAGE "s6-svlisten [ -U | -u | -d | -D | -r | -R ] [ -a | -o ] [ -t timeout ] servicedir... \"\" prog..."
#define dieusage() strerr_dieusage(100, USAGE)
-int main (int argc, char const **argv, char const *const *envp)
+int main (int argc, char const **argv)
{
tain deadline, tto ;
int argc1 ;
@@ -67,11 +69,11 @@ int main (int argc, char const **argv, char const *const *envp)
s6_svlisten_t foo = S6_SVLISTEN_ZERO ;
pid_t pid ;
unsigned int e ;
- uint16_t ids[argc1] ;
+ uint32_t ids[argc1] ;
unsigned char upstate[bitarray_div8(argc1)] ;
unsigned char readystate[bitarray_div8(argc1)] ;
s6_svlisten_init(argc1, argv, &foo, ids, upstate, readystate, &deadline) ;
- pid = cspawn(argv[argc1 + 1], argv + argc1 + 1, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
+ pid = cspawn(argv[argc1 + 1], argv + argc1 + 1, (char const *const *)environ, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ;
if (wantup == 2)
{
@@ -82,5 +84,5 @@ int main (int argc, char const **argv, char const *const *envp)
e = s6_svlisten_loop(&foo, wantup, wantready, or, &deadline, selfpipe_fd(), &s6_svlisten_signal_handler) ;
if (e) strerr_dief1x(e, "some services reported permanent failure or their supervisor died") ;
}
- return 0 ;
+ _exit(0) ;
}
diff --git a/src/supervision/s6-svlisten.h b/src/supervision/s6-svlisten.h
index a0aa591..a90febc 100644
--- a/src/supervision/s6-svlisten.h
+++ b/src/supervision/s6-svlisten.h
@@ -13,9 +13,9 @@ typedef action_func *action_func_ref ;
typedef struct s6_svlisten_s s6_svlisten_t, *s6_svlisten_t_ref ;
struct s6_svlisten_s
{
- ftrigr_t a ;
+ ftrigr a ;
unsigned int n ;
- uint16_t *ids ;
+ uint32_t *ids ;
unsigned char *upstate ;
unsigned char *readystate ;
} ;
@@ -23,7 +23,7 @@ struct s6_svlisten_s
extern void s6_svlisten_signal_handler (void) ;
extern void s6_svlisten_selfpipe_init (void) ;
-extern void s6_svlisten_init (int, char const *const *, s6_svlisten_t *, uint16_t *, unsigned char *, unsigned char *, tain const *) ;
+extern void s6_svlisten_init (int, char const *const *, s6_svlisten_t *, uint32_t *, unsigned char *, unsigned char *, tain const *) ;
extern unsigned int s6_svlisten_loop (s6_svlisten_t *, int, int, int, tain const *, int, action_func_ref) ;
#endif
diff --git a/src/supervision/s6-svlisten1.c b/src/supervision/s6-svlisten1.c
index 4289e8c..cfda1af 100644
--- a/src/supervision/s6-svlisten1.c
+++ b/src/supervision/s6-svlisten1.c
@@ -1,7 +1,9 @@
/* ISC license. */
#include
+#include
+#include
#include
#include
#include
@@ -14,13 +16,13 @@
#define USAGE "s6-svlisten1 [ -U | -u | -d | -D | -r | -R ] [ -t timeout ] servicedir prog..."
#define dieusage() strerr_dieusage(100, USAGE)
-int main (int argc, char const *const *argv, char const *const *envp)
+int main (int argc, char const *const *argv)
{
s6_svlisten_t foo = S6_SVLISTEN_ZERO ;
tain deadline, tto ;
pid_t pid ;
int wantup = 1, wantready = 0, wantrestart = 0 ;
- uint16_t id ;
+ uint32_t id ;
unsigned char upstate, readystate ;
PROG = "s6-svlisten1" ;
{
@@ -50,12 +52,12 @@ int main (int argc, char const *const *argv, char const *const *envp)
tain_add_g(&deadline, &tto) ;
s6_svlisten_selfpipe_init() ;
s6_svlisten_init(1, argv, &foo, &id, &upstate, &readystate, &deadline) ;
- pid = cspawn(argv[1], argv + 1, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
+ pid = cspawn(argv[1], argv + 1, (char const *const *)environ, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ;
if (wantrestart)
if (s6_svlisten_loop(&foo, 0, 1, 1, &deadline, selfpipe_fd(), &s6_svlisten_signal_handler))
strerr_dief2x(1, argv[0], " failed permanently or its supervisor died") ;
if (s6_svlisten_loop(&foo, wantup, wantready, 1, &deadline, selfpipe_fd(), &s6_svlisten_signal_handler))
strerr_dief2x(1, argv[0], " failed permanently or its supervisor died") ;
- return 0 ;
+ _exit(0) ;
}
diff --git a/src/supervision/s6-svscan.c b/src/supervision/s6-svscan.c
index f943965..cf73c13 100644
--- a/src/supervision/s6-svscan.c
+++ b/src/supervision/s6-svscan.c
@@ -10,10 +10,9 @@
#include
#include
-#include
-#include
#include
-#include
+#include
+#include
#include
#include
#include
@@ -22,7 +21,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -32,7 +30,7 @@
#include
-#define USAGE "s6-svscan [ -c services_max | -C services_max ] [ -L name_max ] [ -t timeout ] [ -d notif ] [ -X consoleholder ] [ dir ]"
+#define USAGE "s6-svscan [ -C services_max ] [ -L name_max ] [ -t timeout ] [ -d notif ] [ -X consoleholder ] scandir"
#define dieusage() strerr_dieusage(100, USAGE)
#define CTL S6_SVSCAN_CTLDIR "/control"
@@ -43,6 +41,16 @@
#define SIGNAL_PROG_LEN (sizeof(SIGNAL_PROG) - 1)
#define SPECIAL_LOGGER_SERVICE "s6-svscan-log"
+enum gola_e
+{
+ GOLA_MAX,
+ GOLA_NAMEMAX,
+ GOLA_TIMEOUT,
+ GOLA_NOTIF,
+ GOLA_CONSOLE,
+ GOLA_N
+} ;
+
typedef struct service_s service, *service_ref ;
struct service_s
{
@@ -658,82 +666,92 @@ static inline int control_init (void)
int main (int argc, char const *const *argv)
{
+ static gol_arg const rgola[GOLA_N] =
+ {
+ { .so = 'C', .lo = "services-max", .i = GOLA_MAX },
+ { .so = 'L', .lo = "name-max", .i = GOLA_NAMEMAX },
+ { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT },
+ { .so = 'd', .lo = "notification-fd", .i = GOLA_NOTIF },
+ { .so = 'X', .lo = "console-holder", .i = GOLA_CONSOLE },
+ } ;
iopause_fd x[2] = { { .fd = -1, .events = IOPAUSE_READ }, { .fd = -1, .events = IOPAUSE_READ } } ;
- PROG = "s6-svscan" ;
+ unsigned int notif = 0 ;
+ sigset_t set ;
+ char const *wgola[GOLA_N] = { 0 } ;
+ unsigned int golc ;
+ PROG = "s6-svscan" ;
+ golc = gol_main(argc, argv, 0, 0, rgola, GOLA_N, 0, wgola) ;
+ argc -= golc ; argv += golc ;
+ if (argc < 2) dieusage() ;
+ if (wgola[GOLA_MAX])
{
- subgetopt l = SUBGETOPT_ZERO ;
- unsigned int notif = 0 ;
- unsigned int t = 0 ;
- for (;;)
- {
- int opt = subgetopt_r(argc, argv, "c:C:L:t:d:X:", &l) ;
- if (opt == -1) break ;
- switch (opt)
- {
- case 'c' : if (!uint320_scan(l.arg, &max)) dieusage() ; max <<= 1 ; break ;
- case 'C' : if (!uint320_scan(l.arg, &max)) dieusage() ; break ;
- case 'L' : if (!uint320_scan(l.arg, &namemax)) dieusage() ; break ;
- case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
- case 'd' : if (!uint0_scan(l.arg, ¬if)) dieusage() ; break ;
- case 'X' : if (!uint0_scan(l.arg, &consoleholder)) dieusage() ; break ;
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- if (t) tain_from_millisecs(&scantto, t) ;
+ if (!uint320_scan(wgola[GOLA_MAX], &max))
+ strerr_dief2x(100, "services_max", " must be an unsigned integer") ;
if (max < 4) max = 4 ;
if (max > 160000) max = 160000 ;
- special = max ;
+ }
+ if (wgola[GOLA_NAMEMAX])
+ {
+ if (!uint320_scan(wgola[GOLA_NAMEMAX], &max))
+ strerr_dief2x(100, "name_max", " must be an unsigned integer") ;
if (namemax < 11) namemax = 11 ;
if (namemax > 1019) namemax = 1019 ;
+ }
+ if (wgola[GOLA_TIMEOUT])
+ {
+ unsigned int t = 0 ;
+ if (!uint0_scan(wgola[GOLA_TIMEOUT], &t))
+ strerr_dief2x(100, "timeout", " must be an unsigned integer") ;
+ if (t) tain_from_millisecs(&scantto, t) ;
+ }
+ if (wgola[GOLA_NOTIF])
+ {
+ if (!uint0_scan(wgola[GOLA_NOTIF], ¬if))
+ strerr_dief2x(100, "notif", " must be an unsigned integer") ;
+ if (notif < 3) strerr_dief2x(100, "notif", " must be 3 or more") ;
+ if (fcntl(notif, F_GETFD) == -1) strerr_dief1sys(100, "invalid notification fd") ;
+ }
+ if (wgola[GOLA_CONSOLE])
+ {
+ if (!uint0_scan(wgola[GOLA_CONSOLE], &consoleholder))
+ strerr_dief2x(100, "consoleholder", " must be an unsigned integer") ;
+ if (consoleholder < 3) strerr_dief2x(100, "consoleholder", " must be 3 or more") ;
+ if (fcntl(consoleholder, F_GETFD) == -1) strerr_dief1sys(100, "invalid console holder fd") ;
+ if (coe(consoleholder) == -1) strerr_diefu1sys(111, "coe console holder") ;
+ }
- if (notif)
- {
- if (notif < 3) strerr_dief1x(100, "notification fd must be 3 or more") ;
- if (fcntl(notif, F_GETFD) == -1) strerr_dief1sys(100, "invalid notification fd") ;
- }
- if (consoleholder)
- {
- if (consoleholder < 3) strerr_dief1x(100, "console holder fd must be 3 or more") ;
- if (fcntl(consoleholder, F_GETFD) < 0) strerr_dief1sys(100, "invalid console holder fd") ;
- if (coe(consoleholder) == -1) strerr_diefu1sys(111, "coe console holder") ;
- }
- if (!fd_sanitize()) strerr_diefu1x(100, "sanitize standard fds") ;
-
- if (argc && (chdir(argv[0]) == -1)) strerr_diefu1sys(111, "chdir") ;
- x[1].fd = control_init() ;
- x[0].fd = selfpipe_init() ;
- if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ;
- if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ;
-
- {
- sigset_t set ;
- sigemptyset(&set) ;
- sigaddset(&set, SIGCHLD) ;
- sigaddset(&set, SIGALRM) ;
- sigaddset(&set, SIGABRT) ;
- sigaddset(&set, SIGHUP) ;
- sigaddset(&set, SIGINT) ;
- sigaddset(&set, SIGTERM) ;
- sigaddset(&set, SIGQUIT) ;
- sigaddset(&set, SIGUSR1) ;
- sigaddset(&set, SIGUSR2) ;
+ special = max ;
+ if (!fd_sanitize()) strerr_diefu1x(100, "sanitize standard fds") ;
+ if (chdir(argv[0]) == -1) strerr_diefu2sys(111, "chdir to ", argv[0]) ;
+ x[1].fd = control_init() ;
+ x[0].fd = selfpipe_init() ;
+ if (x[0].fd == -1) strerr_diefu1sys(111, "selfpipe_init") ;
+ if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ;
+
+ sigemptyset(&set) ;
+ sigaddset(&set, SIGCHLD) ;
+ sigaddset(&set, SIGALRM) ;
+ sigaddset(&set, SIGABRT) ;
+ sigaddset(&set, SIGHUP) ;
+ sigaddset(&set, SIGINT) ;
+ sigaddset(&set, SIGTERM) ;
+ sigaddset(&set, SIGQUIT) ;
+ sigaddset(&set, SIGUSR1) ;
+ sigaddset(&set, SIGUSR2) ;
#ifdef SIGPWR
- sigaddset(&set, SIGPWR) ;
+ sigaddset(&set, SIGPWR) ;
#endif
#ifdef SIGWINCH
- sigaddset(&set, SIGWINCH) ;
+ sigaddset(&set, SIGWINCH) ;
#endif
- if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ;
- }
+ if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ;
- initial_cleanup() ;
- if (notif)
- {
- write(notif, "\n", 1) ;
- close(notif) ;
- }
+ initial_cleanup() ;
+ if (notif)
+ {
+ write(notif, "\n", 1) ;
+ close(notif) ;
}
{
@@ -802,5 +820,5 @@ int main (int argc, char const *const *argv)
execv(eargv[0], (char **)eargv) ;
if (errno != ENOENT) panicnosp("exec finish script " FINISH_PROG) ;
}
- return 0 ;
+ _exit(0) ;
}
diff --git a/src/supervision/s6-svwait.c b/src/supervision/s6-svwait.c
index 78f5c3f..ca0fd35 100644
--- a/src/supervision/s6-svwait.c
+++ b/src/supervision/s6-svwait.c
@@ -2,6 +2,7 @@
#include
#include
+#include
#include
#include
@@ -52,7 +53,7 @@ int main (int argc, char const *const *argv)
{
s6_svlisten_t foo = S6_SVLISTEN_ZERO ;
unsigned int e ;
- uint16_t ids[argc] ;
+ uint32_t ids[argc] ;
unsigned char upstate[bitarray_div8(argc)] ;
unsigned char readystate[bitarray_div8(argc)] ;
if (!sig_ignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ;
@@ -66,5 +67,5 @@ int main (int argc, char const *const *argv)
e = s6_svlisten_loop(&foo, wantup, wantready, or, &deadline, -1, 0) ;
if (e) strerr_dief1x(e, "some services reported permanent failure or their supervisor died") ;
}
- return 0 ;
+ _exit(0) ;
}
diff --git a/src/supervision/s6_svlisten_loop.c b/src/supervision/s6_svlisten_loop.c
index d7234b1..4a3e4cf 100644
--- a/src/supervision/s6_svlisten_loop.c
+++ b/src/supervision/s6_svlisten_loop.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include
+#include
#include
#include
@@ -16,7 +17,7 @@
#include
#include "s6-svlisten.h"
-void s6_svlisten_init (int argc, char const *const *argv, s6_svlisten_t *foo, uint16_t *ids, unsigned char *upstate, unsigned char *readystate, tain const *deadline)
+void s6_svlisten_init (int argc, char const *const *argv, s6_svlisten_t *foo, uint32_t *ids, unsigned char *upstate, unsigned char *readystate, tain const *deadline)
{
gid_t gid = getegid() ;
unsigned int i = 0 ;
@@ -34,8 +35,8 @@ void s6_svlisten_init (int argc, char const *const *argv, s6_svlisten_t *foo, ui
s[len] = '/' ;
memcpy(s + len + 1, S6_SUPERVISE_EVENTDIR, sizeof(S6_SUPERVISE_EVENTDIR)) ;
ftrigw_fifodir_make(s, gid, 0) ;
- foo->ids[i] = ftrigr_subscribe_g(&foo->a, s, "[DuUdOx]", FTRIGR_REPEAT, deadline) ;
- if (!foo->ids[i]) strerr_diefu2sys(111, "subscribe to events for ", argv[i]) ;
+ if (!ftrigr_subscribe_g(&foo->a, foo->ids + i, FTRIGR_REPEAT, 0, s, "[DuUdOx]", deadline))
+ strerr_diefu2sys(111, "subscribe to events for ", argv[i]) ;
if (!s6_svstatus_read(argv[i], &status)) strerr_diefu1sys(111, "s6_svstatus_read") ;
bitarray_poke(foo->upstate, i, status.pid && !status.flagfinishing) ;
bitarray_poke(foo->readystate, i, status.flagready) ;
@@ -56,7 +57,6 @@ unsigned int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, in
{
iopause_fd x[2] = { { .fd = ftrigr_fd(&foo->a), .events = IOPAUSE_READ }, { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } } ;
unsigned int e = 0 ;
- stralloc sa = STRALLOC_ZERO ;
if (got(foo, wantup, wantready, or)) return 0 ;
for (;;)
@@ -67,19 +67,18 @@ unsigned int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, in
if (x[1].revents & IOPAUSE_READ) (*handler)() ;
if (x[0].revents & IOPAUSE_READ)
{
- unsigned int i = 0 ;
if (ftrigr_update(&foo->a) < 0) strerr_diefu1sys(111, "ftrigr_update") ;
- for (; i < foo->n ; i++)
+ for (unsigned int i = 0 ; i < foo->n ; i++)
{
- sa.len = 0 ;
- r = ftrigr_checksa(&foo->a, foo->ids[i], &sa) ;
- if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ;
+ struct iovec v ;
+ r = ftrigr_peek(&foo->a, foo->ids[i], &v) ;
+ if (r == -1) strerr_diefu1sys(111, "ftrigr_check") ;
else if (r)
{
- size_t j = 0 ;
- for (; j < sa.len ; j++)
+ char const *s = v.iov_base ;
+ for (size_t j = 0 ; j < v.iov_len ; j++)
{
- if (sa.s[j] == 'x')
+ if (s[j] == 'x')
{
if (bitarray_peek(foo->upstate, i) != wantup
|| bitarray_peek(foo->readystate, i) != wantready)
@@ -87,7 +86,7 @@ unsigned int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, in
bitarray_poke(foo->upstate, i, wantup) ;
bitarray_poke(foo->readystate, i, wantready) ;
}
- else if (sa.s[j] == 'O')
+ else if (s[j] == 'O')
{
if (wantup)
{
@@ -98,17 +97,21 @@ unsigned int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, in
}
else
{
- unsigned int d = byte_chr("dDuU", 4, sa.s[j]) ;
+ unsigned int d = byte_chr("dDuU", 4, s[j]) ;
bitarray_poke(foo->upstate, i, d & 2) ;
bitarray_poke(foo->readystate, i, d & 1) ;
}
- if (got(foo, wantup, wantready, or)) goto gotit ;
+ if (got(foo, wantup, wantready, or))
+ {
+ ftrigr_ack(&foo->a, foo->ids[i]) ;
+ goto gotit ;
+ }
}
+ ftrigr_ack(&foo->a, foo->ids[i]) ;
}
}
}
}
gotit:
- stralloc_free(&sa) ;
return e ;
}
--
cgit v1.3.1
From 4cdcab0506e76666800d2bc111c602bb3154cc30 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Tue, 17 Mar 2026 16:00:25 +0000
Subject: s6-svscan trivial fix; s6-svunlink bugfix; start prep for 2.15.0.0
s6_supervise_unlink_names can spawn a s6-ftrigrd to wait for an 'x'
event. This creates a fifodir under $scandir/$name/event. But after
the unlink, $scandir/$name doesn't exist anymore, so s6-ftrigrd
fails to clean it up. To fix that, we subscribe with the realpath
of $scandir/$name instead.
---
package/info | 2 +-
src/libs6/s6_supervise_unlink_names.c | 14 ++++++++++----
src/supervision/s6-svscan.c | 2 +-
3 files changed, 12 insertions(+), 6 deletions(-)
(limited to 'src/supervision')
diff --git a/package/info b/package/info
index 8c56c0c..edaa30f 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
package=s6
-version=2.14.0.1
+version=2.15.0.0
category=admin
package_macro_name=S6
diff --git a/src/libs6/s6_supervise_unlink_names.c b/src/libs6/s6_supervise_unlink_names.c
index d8bb4e0..a6c7be5 100644
--- a/src/libs6/s6_supervise_unlink_names.c
+++ b/src/libs6/s6_supervise_unlink_names.c
@@ -8,14 +8,18 @@
#include
#include
+#include
+#include
#include
#include
-static int registerit (ftrigr *a, uint32_t *id, char *fn, size_t len, tain const *deadline, tain *stamp)
+static int registerit (ftrigr *a, uint32_t *id, char *fn, size_t len, stralloc *sa, tain const *deadline, tain *stamp)
{
memcpy(fn + len, "/" S6_SUPERVISE_EVENTDIR, sizeof(S6_SUPERVISE_EVENTDIR) + 1) ;
- return ftrigr_subscribe(a, id, 0, 0, fn, "x", deadline, stamp) ;
+ sa->len = 0 ;
+ if (sarealpath(sa, fn) == -1) return 0 ;
+ return ftrigr_subscribe(a, id, 0, 0, sa->s, "x", deadline, stamp) ;
}
/*
@@ -63,6 +67,7 @@ int s6_supervise_unlink_names (char const *scdir, char const *const *names, size
{
ftrigr a = FTRIGR_ZERO ;
+ stralloc sa = STRALLOC_ZERO ;
unsigned int m = 0 ;
uint32_t ids[ntotal] ;
if (options & 1 && !ftrigr_startf(&a, deadline, stamp)) return -1 ;
@@ -75,11 +80,11 @@ int s6_supervise_unlink_names (char const *scdir, char const *const *names, size
memcpy(fn + scdirlen + 1, names[i], nlen) ;
if (options & 1 && bitarray_peek(locked, i))
{
- if (registerit(&a, ids + m, fn, scdirlen + 1 + nlen, deadline, stamp)) m++ ;
+ if (registerit(&a, ids + m, fn, scdirlen + 1 + nlen, &sa, deadline, stamp)) m++ ;
if (bitarray_peek(logged, i))
{
memcpy(fn + scdirlen + 1 + nlen, "/log", 4) ;
- if (registerit(&a, ids + m, fn, scdirlen + 5 + nlen, deadline, stamp)) m++ ;
+ if (registerit(&a, ids + m, fn, scdirlen + 5 + nlen, &sa, deadline, stamp)) m++ ;
}
}
fn[scdirlen + 1 + nlen] = 0 ;
@@ -88,6 +93,7 @@ int s6_supervise_unlink_names (char const *scdir, char const *const *names, size
s6_svc_writectl(scdir, S6_SVSCAN_CTLDIR, "an", 2) ;
if (options & 1)
{
+ stralloc_free(&sa) ;
ftrigr_wait_and(&a, ids, m, deadline, stamp) ;
ftrigr_end(&a) ;
}
diff --git a/src/supervision/s6-svscan.c b/src/supervision/s6-svscan.c
index cf73c13..2f425a2 100644
--- a/src/supervision/s6-svscan.c
+++ b/src/supervision/s6-svscan.c
@@ -683,7 +683,7 @@ int main (int argc, char const *const *argv)
PROG = "s6-svscan" ;
golc = gol_main(argc, argv, 0, 0, rgola, GOLA_N, 0, wgola) ;
argc -= golc ; argv += golc ;
- if (argc < 2) dieusage() ;
+ if (!argc) dieusage() ;
if (wgola[GOLA_MAX])
{
if (!uint320_scan(wgola[GOLA_MAX], &max))
--
cgit v1.3.1
From 24637cd3776cda5fd0a919ba9343ba86d82d3e04 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Wed, 18 Mar 2026 01:57:01 +0000
Subject: More fixes, ftrigr_string addition, doc update
---
INSTALL | 2 +-
NEWS | 13 ++++
doc/index.html | 6 +-
doc/libs6/ftrigr.html | 132 +++++++++++++++++--------------------
doc/libs6/s6-ftrigrd.html | 37 +++++------
doc/s6-setsid.html | 3 +-
doc/upgrade.html | 17 +++++
package/deps.mak | 9 ++-
src/include/s6/ftrigr.h | 13 ++--
src/libs6/deps-lib/s6 | 1 -
src/libs6/ftrigr_peek.c | 7 +-
src/libs6/ftrigr_peek1.c | 14 ----
src/libs6/ftrigr_wait_and.c | 4 +-
src/libs6/ftrigr_wait_or.c | 5 +-
src/pipe-tools/s6-ftrig-listen.c | 4 +-
src/pipe-tools/s6-ftrig-listen1.c | 6 +-
src/pipe-tools/s6-ftrig-wait.c | 6 +-
src/supervision/s6-notifyoncheck.c | 6 +-
src/supervision/s6_svlisten_loop.c | 13 ++--
19 files changed, 151 insertions(+), 147 deletions(-)
delete mode 100644 src/libs6/ftrigr_peek1.c
(limited to 'src/supervision')
diff --git a/INSTALL b/INSTALL
index dd6bdaf..2cb405e 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,7 +6,7 @@ Build Instructions
- A POSIX-compliant C development environment
- GNU make version 3.81 or later
- - skalibs version 2.14.5.1 or later: https://skarnet.org/software/skalibs/
+ - skalibs version 2.14.6.0 or later: https://skarnet.org/software/skalibs/
- Recommended: execline version 2.9.8.1 or later: https://skarnet.org/software/execline/
(You can disable this requirement at configure time, but will
lose some functionality.)
diff --git a/NEWS b/NEWS
index 061674f..a2f6592 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,18 @@
Changelog for s6.
+In 2.15.0.0
+-----------
+
+ - Bugfixes.
+ - s6-svscan's scandir argument is now mandatory.
+ - s6-setsid now autodetects its controlling terminal by default.
+ - Complete ftrigr refactor. This doesn't impact CLI programs,
+except the next point.
+ - s6-ftrig-wait and s6-ftrig-listen1 now print the whole
+sequence of events (followed by a newline) to stdout, rather than
+just the triggering event.
+
+
In 2.14.0.1
-----------
diff --git a/doc/index.html b/doc/index.html
index 1baa6ab..925661e 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -83,7 +83,7 @@ with s6
A POSIX-compliant system with a standard C development environment
GNU make, version 3.81 or later
skalibs version
-2.14.5.1 or later. It's a build-time requirement. It's also a run-time
+2.14.6.0 or later. It's a build-time requirement. It's also a run-time
requirement if you link against the shared version of the skalibs
library.
(Optional, but really recommended for full functionality):
@@ -115,8 +115,8 @@ want nsswitch-like functionality:
Download
- - The current released version of s6 is 2.14.0.1.
-You can access its checksum here.
+ - The current released version of s6 is 2.15.0.0.
+You can access its checksum here.
- Alternatively, you can checkout a copy of the
s6
git repository:
diff --git a/doc/libs6/ftrigr.html b/doc/libs6/ftrigr.html
index 052d7bf..a8cf98b 100644
--- a/doc/libs6/ftrigr.html
+++ b/doc/libs6/ftrigr.html
@@ -43,11 +43,6 @@ and to always use wait_nohang() to reap children,
simply ignoring pids you don't know.
-
- If your application has trouble handling unknown
-children, consider using an ftrigrd service. (And fix your application!)
-
-
A programming example
@@ -61,8 +56,8 @@ for instance, illustrate how to use the ftrigr library.
- - Synchronous functions take a tain_t const *
-(deadline) parameter and a tain_t * (stamp)
+
- Synchronous functions take a tain const *
+(deadline) parameter and a tain * (stamp)
parameter. Those are pointers to tain_t structures containing absolute times;
the former represents a deadline (in most cases, this time will be in the
future) and the latter must be an accurate enough timestamp. These
@@ -100,28 +95,25 @@ control on.
Starting and ending a session
-ftrigr_t a = FTRIGR_ZERO ;
+ftrigr a = FTRIGR_ZERO ;
tain_t deadline, stamp ;
tain_now(&stamp) ;
tain_addsec(&deadline, &stamp, 2)
-// char const *path = FTRIGR_IPCPATH ;
-// ftrigr_start(&a, path, &deadline, &stamp) ;
ftrigr_startf(&a, &deadline, &stamp) ;
-ftrigr_start starts a session with an ftrigrd service listening on
-path.
ftrigr_startf starts a session with an ftrigrd process as a child
(which is the simplest usage).
-a is an ftrigr_t structure that must be declared in the stack and
-initialized to FTRIGR_ZERO.
+a is an ftrigr structure that can be declared in the stack and
+must be initialized to FTRIGR_ZERO.
stamp must be an accurate enough timestamp.
If the session initialization fails, the function returns 0 and errno is set;
else the function returns 1.
+
If the absolute time deadline is reached and the function
has not returned yet, it immediately returns 0 with errno set to ETIMEDOUT.
@@ -135,8 +127,8 @@ problem with the underlying processes.
You can have more than one session open in parallel, by declaring
-several distinct ftrigr_t structures and calling
-ftrigr_startf (or ftrigr_start) more than once.
+several distinct ftrigr structures and calling
+ftrigr_startf more than once.
However, this is useless, since one single session can handle
virtually as many concurrent fifodirs as your application needs.
@@ -156,8 +148,10 @@ ftrigr_end(&a) ;
char const *path = "/var/lib/myservice/fifodir" ;
char const *re = "a.*b|c*d" ;
uint32_t options = 0 ;
+uint32_t timeout = 60000 ;
+uint32_t id ;
-uint16_t id = ftrigr_subscribe (&a, path, re, options, &deadline, &stamp) ;
+int r = ftrigr_subscribe(&a, &id, options, timeout, path, re, options, &deadline, &stamp) ;
@@ -165,7 +159,9 @@ uint16_t id = ftrigr_subscribe (&a, path, re, options, &deadline, &s
s6-ftrigrd daemon, related to the open
session represented by the a structure, to subscribe to the
path fifodir, and to notify the application when it receives
-a series of events that matches the re regexp.
+a series of events that matches the re regexp.
+
+
options can be 0 or FTRIGR_REPEAT. If it is 0, the daemon will
automatically unsubscribe from path once re has been
matched by a series of events. If it is FTRIGR_REPEAT, it will remain
@@ -173,8 +169,16 @@ subscribed until told otherwise.
- ftrigr_subscribe() returns 0 and sets errno in case of failure, or
-a nonzero 16-bit number identifying the subscription in case of success.
+ If timeout is nonzero, it represents a number of milliseconds;
+after this delay, the daemon will automatically unsubscribe from
+path and report an ETIMEDOUT error to the client. It is not
+advised to use a nonzero timeout along with the FTRIGR_REPEAT option.
+
+
+
+ If it fails, ftrigr_subscribe() returns 0 and sets errno. If
+it succeeds, it returns 1 and stores a number identifying the subscription
+into id.
@@ -188,26 +192,29 @@ and events can be sent without the risk of a race condition.
Synchronously waiting for events
-uint16_t list[1] ;
+uint32_t list[1] = { id } ;
unsigned int n = 1 ;
-char trigger ;
-list[0] = id ;
+ftrigr_string fs ;
// r = ftrigr_wait_and(&a, list, n, &deadline, &stamp) ;
-r = ftrigr_wait_or(&a, list, n, &deadline, &stamp, &trigger) ;
+r = ftrigr_wait_or(&a, list, n, &deadline, &stamp, &fs) ;
ftrigr_wait_and() waits for all the n fifodirs
whose ids are listed in list to receive an event. It returns -1
-in case of error or timeout, or a non-negative integer in case of success.
+in case of error or timeout, or a non-negative integer in case of success.
+
+
+
ftrigr_wait_or() waits for one of the n fifodirs
whose ids are listed in list to receive an event. It returns -1
in case of error or timeout; if it succeeds, the return value is the
position in list, starting at 0, of the identifier that received
-an event; and trigger is set to the character that triggered that
-event, i.e. the last character of a sequence that matched the regular
-expression re used in the subscription.
+an event; and fs is the list of events that were received
+since the subscription and matched the re regular expression.
+fs.s is a char * pointing to the (not null-terminated)
+string of events, and fs.len is its length.
Asynchronously waiting for events
@@ -218,7 +225,7 @@ of usage examples.)
-int ftrigr_fd (ftrigr_t const *a)
+int ftrigr_fd (ftrigr const *a)
@@ -227,30 +234,19 @@ int ftrigr_fd (ftrigr_t const *a)
-int ftrigr_updateb (ftrigr_t *a)
+int ftrigr_update (ftrigr *a)
Call this function whenever the fd checks readability: it will
update a's internal structures with information from the
-s6-ftrigrd daemon. It returns -1 if an error
-occurs; in case of success, it returns the number of identifiers for
-which something happened.
-
-
-
- When ftrigr_updateb returns,
-genalloc_s(uint16_t, &a->list) points to an array of
-genalloc_len(uint16_t, &a->list) 16-bit unsigned
-integers. Those integers are ids waiting to be passed to
-ftrigr_check or ftrigr_checksa.
-The number of ids already acknowledged is stored in
-a->head, so the first unacknowledged id is
-genalloc_s(uint16_t, &a->list)[a->head].
+s6-ftrigrd daemon. It returns -1 (and sets
+errno) if an error occurs, 0 if there were no events, and 1 if events
+were received.
-int ftrigr_check (ftrigr_t *a, uint16_t id, char *what)
+int ftrigr_peek (ftrigr *a, uint32_t id, ftrigr_string *fs)
@@ -263,49 +259,39 @@ call to ftrigr_updateb().
number may have been transmitted from
s6-ftrigrd.
If no notification happened yet, returns 0.
- If something happened, writes the character that triggered the
-latest notification into what and returns the number of
-times that an event happened to this identifier since the last
-call to ftrigr_check().
+ If something happened, returns 1, and fs contains
+the string of events that were received since the subscription or
+since the last call to ftrigr_ack (see below).
+fs->s is a pointer to the non-null-terminated string,
+and fs->len is its length.
-int ftrigr_checksa (ftrigr_t *a, uint16_t id, stralloc *what)
+void ftrigr_ack (ftrigr *a, uint32_t id)
- Checks whether an event happened to id. Use after a
-call to ftrigr_update(), as an alternative to ftrigr_check().
+ Resets the stored string of events. The next invocation of
+ftrigr_peek() will only show new events, if any.
-
- - If an error occurred, returns -1 and sets errno. The error
-number may have been transmitted from
-s6-ftrigrd.
- - If no notification happened yet, returns 0.
- - If something happened, appends one character to the end of the what
-stralloc
-for every time a notification was triggered since the last call
-to ftrigr_check(). Each character is the one that triggered
-a notification. The function then returns 1.
-
-
-void ftrigr_ack (ftrigr_t *a, size_t n)
+int ftrigr_release (ftrigr *a, uint32_t id)
- Acknowledges reading n ids from the id list updated by
-ftrigr_updateb.
+ Frees the resources used by subscription id. Use this
+after getting an event from a subscription done without the
+FTRIGR_REPEAT flag and reading its results, if you want to
+keep the session open and perform more subscriptions.
-
-int ftrigr_update (ftrigr_t *a)
-
-
- Acknowledges all the pending ids (i.e. clears the stored id list)
-then calls ftrigr_updateb().
+ If subscription id was given the FTRIGR_REPEAT flag,
+use ftrigr_unsubscribe() instead. If you're not going
+to perform other subscriptions, ftrigr_end() will
+free all the resources without you needing to call
+ftrigr_release() first.