From bab6077c7556a8e989e4f77cb8afe8f9c3eb560b Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Sun, 16 Aug 2026 21:40:42 +0900 Subject: [PATCH] srv, ibus: remove the endpoints on a signal too A stopped daemon left its socket and IBus address file behind, since plan9port ends a process on SIGTERM without running exit handlers. Both files now go on a note as well as on exit, and only while they are still the ones this daemon made, so a successor is never robbed of its own. --- ibus.c | 10 ++++++++++ srv.c | 39 ++++++++++++++++++++++++++++++++++----- tests/ipc_live_test.c | 3 +++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/ibus.c b/ibus.c index eb742b6..b443aff 100644 --- a/ibus.c +++ b/ibus.c @@ -69,6 +69,15 @@ unlinkaddr(void) addrino = 0; } +static int +addrnote(void *v, char *note) +{ + USED(v); + USED(note); + unlinkaddr(); + return 0; +} + static void machineidfiles(char *buf, int sz, char **path, int npath) { @@ -984,6 +993,7 @@ ibusinit(void) goto fail; } cleanupregistered = 1; + threadnotify(addrnote, 1); if(writeaddr(addrfile, full) < 0){ fprintf(stderr, "strans: ibus: cannot write %s\n", addrfile); goto fail; diff --git a/srv.c b/srv.c index 24f684b..063e886 100644 --- a/srv.c +++ b/srv.c @@ -5,8 +5,32 @@ #include static char adir[256]; +static char sockpath[sizeof(((struct sockaddr_un*)0)->sun_path)]; +static dev_t sockdev; +static ino_t sockino; static Channel *clientc; +/* Removes the socket only while it is still the one we announced. */ +static void +srvunlink(void) +{ + struct stat st; + + if(sockpath[0] != '\0' && lstat(sockpath, &st) == 0 && + st.st_dev == sockdev && st.st_ino == sockino) + unlink(sockpath); + sockpath[0] = '\0'; +} + +static int +srvnote(void *v, char *note) +{ + USED(v); + USED(note); + srvunlink(); + return 0; +} + static int srvreadreq(int fd, Keyreq *kr, int *want) { @@ -90,18 +114,23 @@ clientthread(void *arg) void srvinit(void) { - char *addr, path[sizeof(((struct sockaddr_un*)0)->sun_path)]; + struct stat st; + char *addr; - if(ipcpath(path, sizeof path) < 0) + if(ipcpath(sockpath, sizeof sockpath) < 0) die("IPC path is too long"); - addr = smprint("unix!%s", path); + addr = smprint("unix!%s", sockpath); if(addr == nil) die("out of memory"); if(announce(addr, adir) < 0) die("IPC endpoint is already in use: %r"); free(addr); - if(chmod(path, 0600) < 0) - die("can't protect IPC endpoint: %s", path); + if(chmod(sockpath, 0600) < 0 || lstat(sockpath, &st) < 0) + die("can't protect IPC endpoint: %s", sockpath); + sockdev = st.st_dev; + sockino = st.st_ino; + atexit(srvunlink); + threadnotify(srvnote, 1); } void diff --git a/tests/ipc_live_test.c b/tests/ipc_live_test.c index 7544193..22ac679 100644 --- a/tests/ipc_live_test.c +++ b/tests/ipc_live_test.c @@ -334,6 +334,9 @@ main(int argc, char **argv) showerrors(&daemon); if(!stopdaemon(&daemon)) ok = 0; + /* SIGTERM must leave no socket behind. */ + if(access(live.socket, F_OK) == 0) + ok = fail("socket %s survived the daemon", live.socket); if(!closeerrors(&daemon)) ok = 0; if(!liveclean(&live))