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