aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/server_epoll.lua3
-rw-r--r--util-src/signal.c69
2 files changed, 63 insertions, 9 deletions
diff --git a/net/server_epoll.lua b/net/server_epoll.lua
index a064dcfa..127d049e 100644
--- a/net/server_epoll.lua
+++ b/net/server_epoll.lua
@@ -1147,12 +1147,13 @@ end
local hook_signal;
if have_signal and signal.signalfd then
local function dispatch(self)
- return self:on("signal", signal.signalfd_read(self:getfd()));
+ return self:on("signal", self.conn:read());
end
function hook_signal(signum, cb)
local watch = watchfd(signal.signalfd(signum), dispatch);
watch.listeners = { onsignal = cb };
+ watch.close = nil; -- revert to default
return watch;
end
end
diff --git a/util-src/signal.c b/util-src/signal.c
index 3af80a73..ef35067b 100644
--- a/util-src/signal.c
+++ b/util-src/signal.c
@@ -373,29 +373,66 @@ static int l_kill(lua_State *L) {
#endif
#ifdef __linux__
-static int l_signalfd(lua_State *L) {
+struct lsignalfd {
+ int fd;
sigset_t mask;
+};
+
+static int l_signalfd(lua_State *L) {
+ struct lsignalfd *sfd = lua_newuserdata(L, sizeof(struct lsignalfd));
- sigemptyset(&mask);
- sigaddset(&mask, luaL_checkinteger(L, 1));
+ sigemptyset(&sfd->mask);
+ sigaddset(&sfd->mask, luaL_checkinteger(L, 1));
- sigprocmask(SIG_BLOCK, &mask, NULL); /* TODO check err */
+ sigprocmask(SIG_BLOCK, &sfd->mask, NULL); /* TODO check err */
- lua_pushinteger(L, signalfd(-1, &mask, SFD_NONBLOCK));
+ sfd->fd = signalfd(-1, &sfd->mask, SFD_NONBLOCK);
+
+ if(sfd->fd == -1) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ luaL_setmetatable(L, "signalfd");
+ return 1;
+}
+
+static int l_signalfd_getfd(lua_State *L) {
+ struct lsignalfd *sfd = luaL_checkudata(L, 1, "signalfd");
+
+ if (sfd->fd == -1) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ lua_pushinteger(L, sfd->fd);
return 1;
}
static int l_signalfd_read(lua_State *L) {
- const int sigfd = luaL_checkinteger(L, 1);
+ struct lsignalfd *sfd = luaL_checkudata(L, 1, "signalfd");
struct signalfd_siginfo siginfo;
- if(read(sigfd, &siginfo, sizeof(siginfo)) < 0) {
+ if(read(sfd->fd, &siginfo, sizeof(siginfo)) < 0) {
return 0;
}
lua_pushinteger(L, siginfo.ssi_signo);
return 1;
}
+
+static int l_signalfd_close(lua_State *L) {
+ struct lsignalfd *sfd = luaL_checkudata(L, 1, "signalfd");
+
+ if(close(sfd->fd) != 0) {
+ lua_pushboolean(L, 0);
+ return 1;
+ }
+
+ sfd->fd = -1;
+ lua_pushboolean(L, 1);
+ return 1;
+}
#endif
static const struct luaL_Reg lsignal_lib[] = {
@@ -406,7 +443,6 @@ static const struct luaL_Reg lsignal_lib[] = {
#endif
#ifdef __linux__
{"signalfd", l_signalfd},
- {"signalfd_read", l_signalfd_read},
#endif
{NULL, NULL}
};
@@ -415,6 +451,23 @@ int luaopen_prosody_util_signal(lua_State *L) {
luaL_checkversion(L);
int i = 0;
+#ifdef __linux__
+ luaL_newmetatable(L, "signalfd");
+ lua_pushcfunction(L, l_signalfd_close);
+ lua_setfield(L, -2, "__gc");
+ lua_createtable(L, 0, 1);
+ {
+ lua_pushcfunction(L, l_signalfd_getfd);
+ lua_setfield(L, -2, "getfd");
+ lua_pushcfunction(L, l_signalfd_read);
+ lua_setfield(L, -2, "read");
+ lua_pushcfunction(L, l_signalfd_close);
+ lua_setfield(L, -2, "close");
+ }
+ lua_setfield(L, -2, "__index");
+ lua_pop(L, 1);
+#endif
+
/* add the library */
lua_newtable(L);
luaL_setfuncs(L, lsignal_lib, 0);