Mercurial > irccd
changeset 1133:8ea7366ef45a
lib: revert to using a pipe for irc_bot_post
Using a signal is discouraged and requires the bot to setup a dummy handler.
Also protect the call to irc_bot_post to be fully threadsafe.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 09 Dec 2021 14:13:14 +0100 |
parents | 6f85c4743494 |
children | e16b0e3a137c |
files | lib/irccd/irccd.c |
diffstat | 1 files changed, 43 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/irccd/irccd.c Thu Dec 09 11:34:49 2021 +0100 +++ b/lib/irccd/irccd.c Thu Dec 09 14:13:14 2021 +0100 @@ -26,6 +26,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <unistd.h> #include <utlist.h> @@ -48,7 +49,9 @@ static struct sigaction sa; static struct defer *queue; +static int pipes[2]; static pthread_t self; +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; static int is_command(const struct irc_plugin *p, const struct irc_event *ev) @@ -240,6 +243,17 @@ return 0; } +static void +pipe_flush(const struct pollfd *fd) +{ + int dummy; + + if (fd->fd != pipes[0] || !(fd->revents & POLLIN)) + return; + if (read(pipes[0], &dummy, sizeof (int)) != sizeof (int)) + irc_util_die("read: %s\n", strerror(errno)); +} + void irc_bot_init(void) { @@ -251,6 +265,8 @@ if (sigaction(SIGCHLD, &sa, NULL) < 0) irc_util_die("sigaction: %s\n", strerror(errno)); + if (pipe(pipes) < 0) + irc_util_die("pipe: %s\n", strerror(errno)); self = pthread_self(); } @@ -566,7 +582,7 @@ size_t irc_bot_poll_size(void) { - size_t i = 0; + size_t i = 1; struct irc_server *s; LL_FOREACH(irc.servers, s) @@ -582,6 +598,10 @@ struct irc_server *s; + fds->fd = pipes[0]; + fds->events = POLLIN; + fds++; + LL_FOREACH(irc.servers, s) irc_server_prepare(s, fds++); } @@ -594,6 +614,8 @@ struct irc_server *s; struct defer *d, *dtmp; + pipe_flush(fds++); + LL_FOREACH_SAFE(queue, d, dtmp) { d->exec(d->data); free(d); @@ -624,6 +646,10 @@ irc_bot_post(void (*exec)(void *), void *data) { struct defer *d; + int dummy = 1; + + if (pthread_mutex_lock(&mtx) < 0) + irc_util_die("pthread_mutex_lock: %s\n", strerror(errno)); d = irc_util_calloc(1, sizeof (*d)); d->exec = exec; @@ -633,13 +659,21 @@ /* Signal only if I'm not the same thread. */ if (!pthread_equal(pthread_self(), self)) - pthread_kill(self, SIGUSR1); + if (write(pipes[1], &dummy, sizeof (int)) != sizeof (int)) + irc_util_die("write: %s\n", strerror(errno)); + + if (pthread_mutex_unlock(&mtx) < 0) + irc_util_die("pthread_mutex_unlock: %s\n", strerror(errno)); } void irc_bot_finish(void) { struct irc_plugin_loader *ld, *ldtmp; + struct defer *d, *dtmp; + + close(pipes[0]); + close(pipes[1]); /* * First remove all loaders to mkae sure plugins won't try to load @@ -648,7 +682,14 @@ LL_FOREACH_SAFE(irc.plugin_loaders, ld, ldtmp) irc_plugin_loader_finish(ld); + /* Remove all deferred calls. */ + LL_FOREACH_SAFE(queue, d, dtmp) + free(d); + + queue = NULL; irc_bot_server_clear(); irc_bot_plugin_clear(); irc_bot_rule_clear(); + + pthread_mutex_destroy(&mtx); }