From 0445f2a3590f67441602a05fe3924ab677c79ff0 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Wed, 14 Jun 2017 04:09:00 +0000 Subject: 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() --- src/include/s6/ftrigr.h | 7 +++--- src/libs6/deps-lib/s6 | 1 + src/libs6/ftrigr_check.c | 39 +++++++++------------------------ src/libs6/ftrigr_checksa.c | 45 ++++++++++++++++++++++++++++++++++++++ src/libs6/ftrigr_subscribe.c | 4 ++-- src/libs6/ftrigr_unsubscribe.c | 2 ++ src/libs6/ftrigr_update.c | 5 +++-- src/supervision/s6_svlisten_loop.c | 41 +++++++++++++++++++++------------- 8 files changed, 93 insertions(+), 51 deletions(-) create mode 100644 src/libs6/ftrigr_checksa.c (limited to 'src') 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 #include #include +#include #include #include #include @@ -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 -#include +#include #include 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 +#include +#include +#include + +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 #include #include +#include #include #include #include @@ -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 #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 ; } -- cgit v1.2.3