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.
This commit is contained in:
2026-08-16 21:40:42 +09:00
parent 48d3e165c3
commit bab6077c75
3 changed files with 47 additions and 5 deletions

10
ibus.c
View File

@@ -69,6 +69,15 @@ unlinkaddr(void)
addrino = 0; addrino = 0;
} }
static int
addrnote(void *v, char *note)
{
USED(v);
USED(note);
unlinkaddr();
return 0;
}
static void static void
machineidfiles(char *buf, int sz, char **path, int npath) machineidfiles(char *buf, int sz, char **path, int npath)
{ {
@@ -984,6 +993,7 @@ ibusinit(void)
goto fail; goto fail;
} }
cleanupregistered = 1; cleanupregistered = 1;
threadnotify(addrnote, 1);
if(writeaddr(addrfile, full) < 0){ if(writeaddr(addrfile, full) < 0){
fprintf(stderr, "strans: ibus: cannot write %s\n", addrfile); fprintf(stderr, "strans: ibus: cannot write %s\n", addrfile);
goto fail; goto fail;

39
srv.c
View File

@@ -5,8 +5,32 @@
#include <sys/un.h> #include <sys/un.h>
static char adir[256]; 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; 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 static int
srvreadreq(int fd, Keyreq *kr, int *want) srvreadreq(int fd, Keyreq *kr, int *want)
{ {
@@ -90,18 +114,23 @@ clientthread(void *arg)
void void
srvinit(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"); die("IPC path is too long");
addr = smprint("unix!%s", path); addr = smprint("unix!%s", sockpath);
if(addr == nil) if(addr == nil)
die("out of memory"); die("out of memory");
if(announce(addr, adir) < 0) if(announce(addr, adir) < 0)
die("IPC endpoint is already in use: %r"); die("IPC endpoint is already in use: %r");
free(addr); free(addr);
if(chmod(path, 0600) < 0) if(chmod(sockpath, 0600) < 0 || lstat(sockpath, &st) < 0)
die("can't protect IPC endpoint: %s", path); die("can't protect IPC endpoint: %s", sockpath);
sockdev = st.st_dev;
sockino = st.st_ino;
atexit(srvunlink);
threadnotify(srvnote, 1);
} }
void void

View File

@@ -334,6 +334,9 @@ main(int argc, char **argv)
showerrors(&daemon); showerrors(&daemon);
if(!stopdaemon(&daemon)) if(!stopdaemon(&daemon))
ok = 0; 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)) if(!closeerrors(&daemon))
ok = 0; ok = 0;
if(!liveclean(&live)) if(!liveclean(&live))