NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/59175: posix_spawn hang, hanging other process too
The attached program appears to reproduce the issue.
make waitrace
./waitraice &
while :; do kill -INFO %1; sleep 1; done
At some point, it will stop printing numbers because it is stuck.
This is probably some deadlock between some combination of p_reflock,
exec_lock, proc_lock, and who knows what other horrible lock
shenanigans posix_spawn gets itself into.
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <spawn.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
unsigned long long n;
static void
info(int signo)
{
char buf[32];
snprintf_ss(buf, sizeof(buf), "%llu\n", n);
(void)write(STDOUT_FILENO, buf, strlen(buf));
}
int
main(int argc, char **argv)
{
static char buf[65536];
int mib[] = {CTL_KERN, KERN_PROC_ARGS, /*pid*/-1, KERN_PROC_NARGV};
sigset_t mask, omask;
if (argc == 2) {
ssize_t nread;
nread = read(STDIN_FILENO, (char[]){0}, 1);
if (nread == -1)
err(1, "read");
if (nread == 0)
errx(1, "premature eof");
return 0;
}
if (sigemptyset(&mask) == -1)
err(1, "sigemptyset");
if (sigaddset(&mask, SIGINFO) == -1)
err(1, "sigaddset");
if (signal(SIGINFO, &info) == SIG_ERR)
err(1, "signal(SIGINFO)");
for (;;) {
char *const nargv[] = {argv[0], "stuff", NULL};
int waitpipe[2];
posix_spawn_file_actions_t fa;
pid_t pid;
size_t buflen;
int status, error;
if (pipe2(waitpipe, O_CLOEXEC) == -1)
err(1, "pipe2");
error = posix_spawn_file_actions_init(&fa);
if (error)
err(1, "posix_spawn_file_actions_init");
error = posix_spawn_file_actions_adddup2(&fa, waitpipe[0],
STDIN_FILENO);
if (error)
err(1, "posix_spawn_file_actions_adddup2");
error = posix_spawn(&pid, nargv[0], &fa, NULL, nargv, NULL);
if (error)
err(1, "posix_spawn");
mib[2] = (int)pid;
buflen = sizeof(buf);
while (sysctl(mib, __arraycount(mib), buf, &buflen, NULL, 0)
== -1) {
if (errno == EBUSY)
continue;
err(1, "sysctl kern.proc_args.%d.nargv", mib[2]);
}
if (close(waitpipe[0]) == -1)
err(1, "close");
if (write(waitpipe[1], (char[]){0}, 1) == -1)
err(1, "write");
if (close(waitpipe[1]))
err(1, "write");
error = posix_spawn_file_actions_destroy(&fa);
if (error)
err(1, "posix_spawn_file_actions_destroy");
if (waitpid(pid, &status, 0) == -1)
err(1, "waitpid");
if (status != 0)
errx(1, "status=0x%x", status);
if (sigprocmask(SIG_BLOCK, &mask, &omask) == -1)
err(1, "sigprocmask(SIG_BLOCK)");
n++;
if (sigprocmask(SIG_SETMASK, &omask, NULL) == -1)
err(1, "sigprocmask(SIG_SETMASK)");
}
printf("%llu\n", n);
fflush(stdout);
return ferror(stdout);
}
Home |
Main Index |
Thread Index |
Old Index