diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2024-05-03 20:43:37 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska@appnovation.com> | 2024-05-03 20:43:37 +0000 |
| commit | 6d0c114f57bcd554383a41c9ca791e25e95b81b5 (patch) | |
| tree | 7ed5e04fa40a18c9e7d1858ae073b9ef602faa3b /src/libs6/s6-ftrigrd.c | |
| parent | 35709f34aaafad99c89d9848b68e3d211b7e0f02 (diff) | |
| download | s6-6d0c114f57bcd554383a41c9ca791e25e95b81b5.tar.gz | |
Restore cleanups in s6-ftrigrd; fix an old bug and a new bug
ftrigw_clean() didn't clean properly.
ftrig1_make() didn't give enough perms to the fifo, notification
could fail in certain cases.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/libs6/s6-ftrigrd.c')
| -rw-r--r-- | src/libs6/s6-ftrigrd.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/src/libs6/s6-ftrigrd.c b/src/libs6/s6-ftrigrd.c index 202ea31..b6ca40b 100644 --- a/src/libs6/s6-ftrigrd.c +++ b/src/libs6/s6-ftrigrd.c @@ -48,26 +48,40 @@ struct ftrigio_s static genalloc g = GENALLOC_ZERO ; /* ftrigio */ +static void ftrigio_deepfree (ftrigio *p) +{ + ftrig1_free(&p->trig) ; + stralloc_free(&p->sa) ; + regfree(&p->re) ; +} + +static void cleanup (void) +{ + size_t n = genalloc_len(ftrigio, &g) ; + ftrigio *a = genalloc_s(ftrigio, &g) ; + for (size_t i = 0 ; i < n ; i++) ftrigio_deepfree(a + i) ; + genalloc_setlen(ftrigio, &g, 0) ; +} + static void trig (uint16_t id, char what, char info) { char pack[4] ; uint16_pack_big(pack, id) ; pack[2] = what ; pack[3] = info ; if (!textmessage_put(textmessage_sender_x, pack, 4)) + { + cleanup() ; strerr_diefu1sys(111, "build answer") ; + } } static void answer (unsigned char c) { if (!textmessage_put(textmessage_sender_1, (char *)&c, 1)) + { + cleanup() ; strerr_diefu1sys(111, "textmessage_put") ; -} - -static void ftrigio_deepfree (ftrigio *p) -{ - ftrig1_free(&p->trig) ; - stralloc_free(&p->sa) ; - regfree(&p->re) ; + } } static void remove (size_t i) @@ -91,7 +105,11 @@ static inline int ftrigio_read (ftrigio *p) if (!r) break ; if (r < 0) return (trig(p->id, 'd', errno), 0) ; blen = buffer_len(&p->b) ; - if (!stralloc_readyplus(&p->sa, blen+1)) dienomem() ; + if (!stralloc_readyplus(&p->sa, blen+1)) + { + cleanup() ; + dienomem() ; + } buffer_getnofill(&p->b, p->sa.s + p->sa.len, blen) ; p->sa.len += blen ; p->sa.s[p->sa.len] = 0 ; @@ -111,7 +129,10 @@ static int parse_protocol (struct iovec const *v, void *context) char const *s = v->iov_base ; uint16_t id ; if (v->iov_len < 3) + { + cleanup() ; strerr_dief1x(100, "invalid client request") ; + } uint16_unpack_big(s, &id) ; switch (s[2]) { @@ -174,6 +195,7 @@ static int parse_protocol (struct iovec const *v, void *context) break ; } default : + cleanup() ; strerr_dief1x(100, "invalid client request") ; } (void)context ; @@ -216,7 +238,10 @@ int main (void) } if (iopause(x, 3 + n, 0, 0) < 0) + { + cleanup() ; strerr_diefu1sys(111, "iopause") ; + } /* client closed */ if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) break ; @@ -224,10 +249,16 @@ int main (void) /* client is reading */ if (x[1].revents & IOPAUSE_WRITE) if (!textmessage_sender_flush(textmessage_sender_1) && !error_isagain(errno)) + { + cleanup() ; strerr_diefu1sys(111, "flush stdout") ; + } if (x[2].revents & IOPAUSE_WRITE) if (!textmessage_sender_flush(textmessage_sender_x) && !error_isagain(errno)) + { + cleanup() ; return 1 ; + } /* scan listening ftrigs */ for (i = 0 ; i < genalloc_len(ftrigio, &g) ; i++) @@ -243,9 +274,11 @@ int main (void) if (textmessage_handle(textmessage_receiver_0, &parse_protocol, 0) < 0) { if (errno == EPIPE) break ; /* normal exit */ + cleanup() ; strerr_diefu1sys(111, "handle messages from client") ; } } } + cleanup() ; return 0 ; } |
