# HG changeset patch # User David Demelier # Date 1638094758 -3600 # Node ID 6457999bfb7ab71dc7d3cf24488a3dd328ff3a9a # Parent 76db0a423f6f4f05fdd55729abd527b1b9f0b69a 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. diff -r 76db0a423f6f -r 6457999bfb7a irccd/main.c --- 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)); diff -r 76db0a423f6f -r 6457999bfb7a lib/CMakeLists.txt --- 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}) diff -r 76db0a423f6f -r 6457999bfb7a lib/irccd/irccd.c --- 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 #include #include #include #include +#include #include #include #include #include -#include #include @@ -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