summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2017-06-14 04:09:00 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2017-06-14 04:09:00 +0000
commit0445f2a3590f67441602a05fe3924ab677c79ff0 (patch)
tree1a011697fbd92ca53468efe019c8c93c364ad6a8 /src
parentf287ac765101f21b530f1a9886e06976c165c922 (diff)
downloads6-0445f2a3590f67441602a05fe3924ab677c79ff0.tar.xz
Add ftrigr_checksa(), rewrite s6_svlisten_loop() around it
- Fixes the race condition hit by permanent failure, i.e. two ftrig events close to each other - Requires storing the sequence of events client-side, so an additional stralloc, bleh - The visible struct ftrigr_s changes, so a major bump is needed -> prepare for 2.6.0.0 - ftrigr_check() is now a trivial wrapper around ftrigr_checksa()
Diffstat (limited to 'src')
-rw-r--r--src/include/s6/ftrigr.h7
-rw-r--r--src/libs6/deps-lib/s61
-rw-r--r--src/libs6/ftrigr_check.c39
-rw-r--r--src/libs6/ftrigr_checksa.c45
-rw-r--r--src/libs6/ftrigr_subscribe.c4
-rw-r--r--src/libs6/ftrigr_unsubscribe.c2
-rw-r--r--src/libs6/ftrigr_update.c5
-rw-r--r--src/supervision/s6_svlisten_loop.c41
8 files changed, 93 insertions, 51 deletions
diff --git a/src/include/s6/ftrigr.h b/src/include/s6/ftrigr.h
index db91ca9..4afbc97 100644
--- a/src/include/s6/ftrigr.h
+++ b/src/include/s6/ftrigr.h
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <skalibs/config.h>
#include <skalibs/tai.h>
+#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/gensetdyn.h>
#include <skalibs/skaclient.h>
@@ -40,11 +41,10 @@ typedef struct ftrigr1_s ftrigr1_t, *ftrigr1_t_ref ;
struct ftrigr1_s
{
uint32_t options ;
- unsigned int count ;
fr1state_t state ;
- char what ;
+ stralloc what ;
} ;
-#define FTRIGR1_ZERO { .options = 0, .count = 0, .state = FR1STATE_ERROR, .what = 0 }
+#define FTRIGR1_ZERO { .options = 0, .state = FR1STATE_ERROR, .what = STRALLOC_ZERO }
extern ftrigr1_t const ftrigr1_zero ;
@@ -76,6 +76,7 @@ extern void ftrigr_end (ftrigr_t *) ;
#define ftrigr_fd(a) skaclient_fd(&(a)->connection)
extern int ftrigr_update (ftrigr_t *) ;
extern int ftrigr_check (ftrigr_t *, uint16_t, char *) ;
+extern int ftrigr_checksa (ftrigr_t *, uint16_t, stralloc *) ;
/* Synchronous functions with timeouts */
diff --git a/src/libs6/deps-lib/s6 b/src/libs6/deps-lib/s6
index 65062e1..ace5a05 100644
--- a/src/libs6/deps-lib/s6
+++ b/src/libs6/deps-lib/s6
@@ -1,5 +1,6 @@
ftrigr1_zero.o
ftrigr_check.o
+ftrigr_checksa.o
ftrigr_end.o
ftrigr_start.o
ftrigr_startf.o
diff --git a/src/libs6/ftrigr_check.c b/src/libs6/ftrigr_check.c
index 0a7fcdc..30be701 100644
--- a/src/libs6/ftrigr_check.c
+++ b/src/libs6/ftrigr_check.c
@@ -1,39 +1,20 @@
/* ISC license. */
#include <errno.h>
-#include <skalibs/gensetdyn.h>
+#include <skalibs/stralloc.h>
#include <s6/ftrigr.h>
int ftrigr_check (ftrigr_t *a, uint16_t id, char *c)
{
- ftrigr1_t *p ;
- if (!id--) return (errno = EINVAL, -1) ;
- p = GENSETDYN_P(ftrigr1_t, &a->data, id) ;
- if (!p) return (errno = EINVAL, -1) ;
- switch (p->state)
+ stralloc sa = STRALLOC_ZERO ;
+ int r = ftrigr_checksa(a, id, &sa) ;
+
+ if (r && sa.len)
{
- case FR1STATE_WAITACKDATA :
- {
- *c = p->what ;
- *p = ftrigr1_zero ;
- gensetdyn_delete(&a->data, id) ;
- return 1 ;
- }
- case FR1STATE_LISTENING :
- {
- unsigned int r = p->count ;
- if (r) *c = p->what ;
- p->count = 0 ;
- return (int)r ;
- }
- case FR1STATE_WAITACK :
- {
- errno = p->what ;
- *p = ftrigr1_zero ;
- gensetdyn_delete(&a->data, id) ;
- return -1 ;
- }
- default: return (errno = EINVAL, -1) ;
+ int e = errno ;
+ *c = sa.s[sa.len - 1] ;
+ stralloc_free(&sa) ;
+ errno = e ;
}
- return 0 ;
+ return r ;
}
diff --git a/src/libs6/ftrigr_checksa.c b/src/libs6/ftrigr_checksa.c
new file mode 100644
index 0000000..6573182
--- /dev/null
+++ b/src/libs6/ftrigr_checksa.c
@@ -0,0 +1,45 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/gensetdyn.h>
+#include <s6/ftrigr.h>
+
+int ftrigr_checksa (ftrigr_t *a, uint16_t id, stralloc *sa)
+{
+ ftrigr1_t *p ;
+ if (!id--) return (errno = EINVAL, -1) ;
+ p = GENSETDYN_P(ftrigr1_t, &a->data, id) ;
+ if (!p) return (errno = EINVAL, -1) ;
+ switch (p->state)
+ {
+ case FR1STATE_WAITACKDATA :
+ {
+ if (!stralloc_catb(sa, p->what.s, p->what.len)) return -1 ;
+ stralloc_free(&p->what) ;
+ *p = ftrigr1_zero ;
+ gensetdyn_delete(&a->data, id) ;
+ return 1 ;
+ }
+ case FR1STATE_LISTENING :
+ {
+ if (!p->what.len) break ;
+ if (!stralloc_catb(sa, p->what.s, p->what.len)) return -1 ;
+ p->what.len = 0 ;
+ return 1 ;
+ }
+ case FR1STATE_WAITACK :
+ {
+ int e ;
+ if (!stralloc_catb(sa, p->what.s, p->what.len - 1)) return -1 ;
+ e = p->what.s[p->what.len - 1] ;
+ stralloc_free(&p->what) ;
+ *p = ftrigr1_zero ;
+ gensetdyn_delete(&a->data, id) ;
+ errno = e ;
+ return -1 ;
+ }
+ default: return (errno = EINVAL, -1) ;
+ }
+ return 0 ;
+}
diff --git a/src/libs6/ftrigr_subscribe.c b/src/libs6/ftrigr_subscribe.c
index 3766d35..cbbde1e 100644
--- a/src/libs6/ftrigr_subscribe.c
+++ b/src/libs6/ftrigr_subscribe.c
@@ -7,6 +7,7 @@
#include <skalibs/uint16.h>
#include <skalibs/uint32.h>
#include <skalibs/tai.h>
+#include <skalibs/stralloc.h>
#include <skalibs/gensetdyn.h>
#include <skalibs/skaclient.h>
#include <s6/ftrigr.h>
@@ -45,8 +46,7 @@ uint16_t ftrigr_subscribe (ftrigr_t *a, char const *path, char const *re, uint32
ftrigr1_t *p = GENSETDYN_P(ftrigr1_t, &a->data, i) ;
p->options = options ;
p->state = FR1STATE_LISTENING ;
- p->count = 0 ;
- p->what = 0 ;
+ p->what = stralloc_zero ;
}
return (uint16_t)(i+1) ;
}
diff --git a/src/libs6/ftrigr_unsubscribe.c b/src/libs6/ftrigr_unsubscribe.c
index 4428b72..a96ddb0 100644
--- a/src/libs6/ftrigr_unsubscribe.c
+++ b/src/libs6/ftrigr_unsubscribe.c
@@ -2,6 +2,7 @@
#include <errno.h>
#include <skalibs/uint16.h>
+#include <skalibs/stralloc.h>
#include <skalibs/gensetdyn.h>
#include <skalibs/skaclient.h>
#include <s6/ftrigr.h>
@@ -30,6 +31,7 @@ int ftrigr_unsubscribe (ftrigr_t *a, uint16_t i, tain_t const *deadline, tain_t
if (!skaclient_send(&a->connection, pack, 3, &skaclient_default_cb, &err, deadline, stamp)) return 0 ;
if (err) return (errno = err, 0) ;
}
+ stralloc_free(&p->what) ;
*p = ftrigr1_zero ;
return gensetdyn_delete(&a->data, i) ;
}
diff --git a/src/libs6/ftrigr_update.c b/src/libs6/ftrigr_update.c
index 52f79b9..f97535d 100644
--- a/src/libs6/ftrigr_update.c
+++ b/src/libs6/ftrigr_update.c
@@ -35,12 +35,14 @@ static int msghandler (unixmessage_t const *m, void *context)
switch (m->s[2])
{
case 'd' :
+ if (!stralloc_catb(&p->what, m->s + 3, 1)) return 0 ;
p->state = FR1STATE_WAITACK ;
break ;
case '!' :
+ if (!stralloc_catb(&p->what, m->s + 3, 1)) return 0 ;
if (p->options & FTRIGR_REPEAT)
{
- if (p->count++
+ if (p->what.len > 1
&& appears(id+1, genalloc_s(uint16_t, &a->list), genalloc_len(uint16_t, &a->list)))
addit = 0 ;
}
@@ -48,7 +50,6 @@ static int msghandler (unixmessage_t const *m, void *context)
break ;
default : return (errno = EPROTO, 0) ;
}
- p->what = m->s[3] ;
if (addit)
{
id++ ; genalloc_append(uint16_t, &a->list, &id) ;
diff --git a/src/supervision/s6_svlisten_loop.c b/src/supervision/s6_svlisten_loop.c
index 5c55c81..c98fe83 100644
--- a/src/supervision/s6_svlisten_loop.c
+++ b/src/supervision/s6_svlisten_loop.c
@@ -5,6 +5,7 @@
#include <skalibs/bitarray.h>
#include <skalibs/strerr2.h>
#include <skalibs/iopause.h>
+#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
#include <s6/ftrigr.h>
#include <s6/s6-supervise.h>
@@ -48,7 +49,10 @@ int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, int or, tai
{
iopause_fd x[2] = { { .fd = ftrigr_fd(&foo->a), .events = IOPAUSE_READ }, { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } } ;
unsigned int e = 0 ;
- while (!got(foo, wantup, wantready, or))
+ stralloc sa = STRALLOC_ZERO ;
+
+ if (got(foo, wantup, wantready, or)) return 0 ;
+ for (;;)
{
int r = iopause_g(x, 1 + (spfd >= 0), deadline) ;
if (r < 0) strerr_diefu1sys(111, "iopause") ;
@@ -60,29 +64,36 @@ int s6_svlisten_loop (s6_svlisten_t *foo, int wantup, int wantready, int or, tai
if (ftrigr_update(&foo->a) < 0) strerr_diefu1sys(111, "ftrigr_update") ;
for (; i < foo->n ; i++)
{
- char what ;
- int r = ftrigr_check(&foo->a, foo->ids[i], &what) ;
+ sa.len = 0 ;
+ r = ftrigr_checksa(&foo->a, foo->ids[i], &sa) ;
if (r < 0) strerr_diefu1sys(111, "ftrigr_check") ;
- if (r)
+ else if (r)
{
- if (what == 'O')
+ size_t j = 0 ;
+ for (; j < sa.len ; j++)
{
- if (wantup)
+ if (sa.s[j] == 'O')
{
- bitarray_poke(foo->upstate, i, wantup) ;
- bitarray_poke(foo->readystate, i, wantready) ;
- e++ ;
+ if (wantup)
+ {
+ bitarray_poke(foo->upstate, i, wantup) ;
+ bitarray_poke(foo->readystate, i, wantready) ;
+ e++ ;
+ }
}
- }
- else
- {
- unsigned int d = byte_chr("dDuU", 4, what) ;
- bitarray_poke(foo->upstate, i, d & 2) ;
- bitarray_poke(foo->readystate, i, d & 1) ;
+ else
+ {
+ unsigned int d = byte_chr("dDuU", 4, sa.s[j]) ;
+ bitarray_poke(foo->upstate, i, d & 2) ;
+ bitarray_poke(foo->readystate, i, d & 1) ;
+ }
+ if (got(foo, wantup, wantready, or)) goto gotit ;
}
}
}
}
}
+ gotit:
+ stralloc_free(&sa) ;
return e ;
}