Mercurial > irccd
changeset 1123:6457999bfb7a
lib: irc_bot_post use a linked list instead
Using a pipe isn't a good idea since it's a byte stream in which every
invocation can arrive partially.
The additional threads now interrupts poll(2) using SIGUSR1.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sun, 28 Nov 2021 11:19:18 +0100 |
parents | 76db0a423f6f |
children | 3d9975880161 |
files | irccd/main.c lib/CMakeLists.txt lib/irccd/irccd.c |
diffstat | 3 files changed, 41 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/irccd/main.c Sat Nov 27 10:06:29 2021 +0100 +++ b/irccd/main.c Sun Nov 28 11:19:18 2021 +0100 @@ -174,6 +174,12 @@ } static void +nada(int signum) +{ + (void)signum; +} + +static void init(void) { struct sigaction sig; @@ -185,9 +191,15 @@ irc_bot_plugin_loader_add(js_plugin_loader_new()); #endif + sigemptyset(&sig.sa_mask); + sig.sa_handler = nada; + + /* Generated from threads. */ + if (sigaction(SIGUSR1, &sig, NULL) < 0) + irc_util_die("sigaction: %s\n", strerror(errno)); + sig.sa_handler = stop; sig.sa_flags = SA_RESTART; - sigemptyset(&sig.sa_mask); if (sigaction(SIGINT, &sig, NULL) < 0 || sigaction(SIGTERM, &sig, NULL) < 0) irc_util_die("sigaction: %s\n", strerror(errno));
--- a/lib/CMakeLists.txt Sat Nov 27 10:06:29 2021 +0100 +++ b/lib/CMakeLists.txt Sun Nov 28 11:19:18 2021 +0100 @@ -105,4 +105,4 @@ ) source_group(extern/libbsd FILES ${LIBBSD_SOURCES}) -source_group(irccd FILES ${SOURCES}) +source_group(irccd FILES ${SOURCES} ${HEADERS})
--- a/lib/irccd/irccd.c Sat Nov 27 10:06:29 2021 +0100 +++ b/lib/irccd/irccd.c Sun Nov 28 11:19:18 2021 +0100 @@ -16,16 +16,15 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/wait.h> #include <assert.h> #include <ctype.h> #include <errno.h> #include <poll.h> +#include <pthread.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <unistd.h> #include <utlist.h> @@ -41,12 +40,14 @@ struct defer { void (*exec)(void *); void *data; + struct defer *next; }; struct irc irc = {0}; -static int pipes[2]; static struct sigaction sa; +static struct defer *queue; +static pthread_t self; static int is_command(const struct irc_plugin *p, const struct irc_event *ev) @@ -170,20 +171,6 @@ irc_plugin_handle(plgcmd, to_command(plgcmd, ev)); } -static void -pipe_flush(const struct pollfd *fd) -{ - struct defer df = {0}; - - if (fd->fd != pipes[0] || !(fd->revents & POLLIN)) - return; - - if (read(fd->fd, &df, sizeof (df)) == sizeof (df)) - df.exec(df.data); - else - irc_log_warn("irccd: %s", strerror(errno)); -} - static struct irc_plugin * find_plugin(struct irc_plugin_loader *ldr, const char *base, const char *name) { @@ -257,16 +244,14 @@ { irc_log_to_console(); - if (pipe(pipes) < 0) - irc_util_die("pipe: %s\n", strerror(errno)); - + sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handle_sigchld; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGCHLD, &sa, NULL) < 0) irc_util_die("sigaction: %s\n", strerror(errno)); + + self = pthread_self(); } void @@ -580,7 +565,7 @@ size_t irc_bot_poll_size(void) { - size_t i = 1; + size_t i = 0; struct irc_server *s; LL_FOREACH(irc.servers, s) @@ -595,13 +580,9 @@ assert(fds); struct irc_server *s; - size_t i = 1; - - fds[0].fd = pipes[0]; - fds[0].events = POLLIN; LL_FOREACH(irc.servers, s) - irc_server_prepare(s, &fds[i++]); + irc_server_prepare(s, fds++); } void @@ -610,12 +591,17 @@ assert(fds); struct irc_server *s; - size_t i = 1; + struct defer *d, *dtmp; - pipe_flush(&fds[0]); + LL_FOREACH_SAFE(queue, d, dtmp) { + d->exec(d->data); + free(d); + } + + queue = NULL; LL_FOREACH(irc.servers, s) - irc_server_flush(s, &fds[i++]); + irc_server_flush(s, fds); } int @@ -636,13 +622,17 @@ void irc_bot_post(void (*exec)(void *), void *data) { - struct defer df = { - .exec = exec, - .data = data - }; + struct defer *d; + + d = irc_util_calloc(1, sizeof (*d)); + d->exec = exec; + d->data = data; - if (write(pipes[1], &df, sizeof (df)) != sizeof (df)) - irc_log_warn("write: %s\n", strerror(errno)); + LL_APPEND(queue, d); + + /* Signal only if I'm not the same thread. */ + if (!pthread_equal(pthread_self(), self)) + pthread_kill(self, SIGUSR1); } void