tests: verify live daemon cleanup

This commit is contained in:
2026-08-14 00:11:03 +09:00
parent 685d78bab5
commit b44663096f
2 changed files with 160 additions and 46 deletions

View File

@@ -228,12 +228,15 @@ startdaemon(Daemon *d, char *program, char *mapdir)
dup2(errpipe[1], STDERR_FILENO) < 0)
_exit(126);
close(errpipe[1]);
setenv("XDG_RUNTIME_DIR", d->runtime, 1);
setenv("XDG_CONFIG_HOME", d->config, 1);
setenv("HOME", d->home, 1);
unsetenv("DISPLAY");
unsetenv("DBUS_SESSION_BUS_ADDRESS");
unsetenv("IBUS_ADDRESS");
if(setenv("XDG_RUNTIME_DIR", d->runtime, 1) < 0 ||
setenv("XDG_CONFIG_HOME", d->config, 1) < 0 ||
setenv("HOME", d->home, 1) < 0 || unsetenv("DISPLAY") < 0 ||
unsetenv("DBUS_SESSION_BUS_ADDRESS") < 0 ||
unsetenv("IBUS_ADDRESS") < 0){
dprintf(STDERR_FILENO, "set daemon environment: %s\n",
strerror(errno));
_exit(126);
}
execl(program, program, mapdir, missing, (char*)0);
dprintf(STDERR_FILENO, "exec %s: %s\n", program, strerror(errno));
_exit(127);
@@ -297,36 +300,82 @@ rmdirknown(char *path)
return fail("rmdir %s: %s", path, strerror(errno));
}
static int
killdaemon(Daemon *d, int *status)
{
int n, ok;
ok = 1;
if(kill(d->pid, SIGKILL) < 0 && errno != ESRCH){
fail("kill -9 %ld: %s", (long)d->pid, strerror(errno));
ok = 0;
}
do
n = waitpid(d->pid, status, 0);
while(n < 0 && errno == EINTR);
if(n != d->pid){
fail("reap %ld after SIGKILL: %s", (long)d->pid,
n < 0 ? strerror(errno) : "wrong child");
ok = 0;
}else
d->pid = -1;
return ok;
}
static int
stopdaemon(Daemon *d)
{
struct pollfd pfd;
int ok, status, n;
int ok, status, n, reaped;
int64_t deadline;
ok = 1;
if(d->pid > 0){
if(kill(d->pid, SIGTERM) < 0 && errno != ESRCH){
do
n = waitpid(d->pid, &status, WNOHANG);
while(n < 0 && errno == EINTR);
if(n == d->pid){
fail("daemon exited before test termination with wait status %#x",
status);
d->pid = -1;
ok = 0;
}else if(n < 0){
fail("check daemon %ld before termination: %s",
(long)d->pid, strerror(errno));
if(errno == ECHILD)
d->pid = -1;
ok = 0;
}
}
if(d->pid > 0){
if(kill(d->pid, SIGTERM) < 0){
fail("kill %ld: %s", (long)d->pid, strerror(errno));
ok = 0;
}
reaped = 0;
deadline = nowms() + Stoptimeout;
for(;;){
n = waitpid(d->pid, &status, WNOHANG);
if(n == d->pid)
if(n == d->pid){
reaped = 1;
d->pid = -1;
break;
if(n < 0 && errno != EINTR){
}
if(n < 0 && errno == EINTR)
continue;
if(n < 0){
fail("waitpid %ld: %s", (long)d->pid, strerror(errno));
ok = 0;
if(errno == ECHILD)
d->pid = -1;
break;
}
n = leftms(deadline);
if(n == 0){
fail("daemon %ld did not stop after SIGTERM", (long)d->pid);
ok = 0;
kill(d->pid, SIGKILL);
while(waitpid(d->pid, &status, 0) < 0 && errno == EINTR)
;
if(!killdaemon(d, &status))
ok = 0;
break;
}
pfd.fd = d->errfd;
@@ -335,14 +384,19 @@ stopdaemon(Daemon *d)
if(poll(&pfd, 1, n) < 0 && errno != EINTR){
fail("poll daemon %ld: %s", (long)d->pid, strerror(errno));
ok = 0;
kill(d->pid, SIGKILL);
while(waitpid(d->pid, &status, 0) < 0 && errno == EINTR)
;
if(!killdaemon(d, &status))
ok = 0;
break;
}
readerrors(d);
}
d->pid = -1;
/* plan9port turns a caught termination note into exit status 1. */
if(reaped &&
!((WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM) ||
(WIFEXITED(status) && WEXITSTATUS(status) == 1))){
fail("daemon exited with unexpected wait status %#x", status);
ok = 0;
}
}
readerrors(d);
if(d->errfd >= 0){