Changeset

13439:1e229d710a3c

util.signal: Add support for signalfd(2) on Linux signalfd allows handling signal events using the same method as sockets, via file descriptors. Thus all signal dispatch can go through the same main event loop as everything else, removing need for thread-scary signal handling where execution would just jump to the signal handler regardless of the state of Lua, and needing to keep track of Lua states/threads.
author Kim Alvefur <zash@zash.se>
date Sat, 24 Feb 2024 00:05:29 +0100
parents 13438:0a0dd2505baa
children 13440:b27de3d2bad6
files util-src/signal.c
diffstat 1 files changed, 34 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/util-src/signal.c	Fri Feb 23 22:45:42 2024 +0000
+++ b/util-src/signal.c	Sat Feb 24 00:05:29 2024 +0100
@@ -32,6 +32,10 @@
 
 #include <signal.h>
 #include <stdlib.h>
+#ifdef __linux__
+#include <unistd.h>
+#include <sys/signalfd.h>
+#endif
 
 #include "lua.h"
 #include "lauxlib.h"
@@ -368,12 +372,42 @@
 
 #endif
 
+#ifdef __linux__
+static int l_signalfd(lua_State *L) {
+	sigset_t mask;
+
+	sigemptyset(&mask);
+	sigaddset(&mask, luaL_checkinteger(L, 1));
+
+	sigprocmask(SIG_BLOCK, &mask, NULL); /* TODO check err */
+
+	lua_pushinteger(L, signalfd(-1, &mask, SFD_NONBLOCK));
+	return 1;
+}
+
+static int l_signalfd_read(lua_State *L) {
+	const int sigfd = luaL_checkinteger(L, 1);
+	struct signalfd_siginfo siginfo;
+
+	if(read(sigfd, &siginfo, sizeof(siginfo)) < 0) {
+		return 0;
+	}
+
+	lua_pushinteger(L, siginfo.ssi_signo);
+	return 1;
+}
+#endif
+
 static const struct luaL_Reg lsignal_lib[] = {
 	{"signal", l_signal},
 	{"raise", l_raise},
 #if defined(__unix__) || defined(__APPLE__)
 	{"kill", l_kill},
 #endif
+#ifdef __linux__
+	{"signalfd", l_signalfd},
+	{"signalfd_read", l_signalfd_read},
+#endif
 	{NULL, NULL}
 };