aboutsummaryrefslogtreecommitdiffstats
path: root/util-src/signal.c
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2024-02-24 00:05:29 +0100
committerKim Alvefur <zash@zash.se>2024-02-24 00:05:29 +0100
commit54f76b97d21b1198916cc354a6a5f7300c2eadc1 (patch)
tree89a9b9ceed9e84b4b09f24ce8d6f598b3e7b1a65 /util-src/signal.c
parentc3af93fce713f8ddc36dc07ad58ccc9d39701836 (diff)
downloadprosody-54f76b97d21b1198916cc354a6a5f7300c2eadc1.tar.gz
prosody-54f76b97d21b1198916cc354a6a5f7300c2eadc1.zip
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.
Diffstat (limited to 'util-src/signal.c')
-rw-r--r--util-src/signal.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/util-src/signal.c b/util-src/signal.c
index a55b6f87..3af80a73 100644
--- a/util-src/signal.c
+++ b/util-src/signal.c
@@ -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 @@ static int l_kill(lua_State *L) {
#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}
};