On Thu, Mar 31, 2011 at 01:17:11PM +0200, Andreas Mohr wrote: > Turns out that dash 0.5.4-12 is NOT affected. Re-upgrading to > current 0.5.5.1-7.4 package then makes it lock up again. > > Non-sudo-prefixed lines (e.g. tested via echo, ls, find, ...) > in the script work fine, it's specifically sudo-based commands which are > problematic. > > > Note that manually executing a test script such as > > #!/bin/sh > > /usr/bin/sudo echo Hi > /usr/bin/sudo whoami > > does terminate properly, when executed as the same user that kvm would > execute the scripts as (and when indeed having dash-as-sh). > Thus it appears that _something_ about the way that kvm sets up its > startup shell scripts context makes things break, i.e. within kvm only. >
The issue here is that QEMU is blocking the SIGCHLD signal before forking, to make sure it won't get any signal due to the child exiting. sigprocmask() settings are inherited during a fork and dash or sudo do use SIGCHLD somewhere in their code, without making sure the signal is enabled. For me it is a bug in dash or sudo. See the attached code for a reduced testcase. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net
#include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char *argv[]) { if (argc > 0) { sigset_t oldmask, mask; int pid, status; char *args[3]; char **parg; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &oldmask); pid = fork(); if (pid == 0) { int open_max = sysconf(_SC_OPEN_MAX), i; for (i = 0; i < open_max; i++) { if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO) { close(i); } } parg = args; *parg++ = (char *)argv[1]; *parg = NULL; execv(argv[1], args); _exit(1); } else if (pid > 0) { while (waitpid(pid, &status, 0) != pid) { /* loop */ } sigprocmask(SIG_SETMASK, &oldmask, NULL); if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { return 0; } } fprintf(stderr, "%s: could not script\n", argv[1]); return -1; } }