Package: sbuild Version: 0.60.5-1 Severity: normal User: ubuntu-de...@lists.ubuntu.com Usertags: origin-ubuntu natty
While trying to build "upstart" in Ubuntu using the latest sbuild, one of the unit tests failed. This was reduced to a test of "raise(SIGTSTP)", which wasn't actually stopping the process. In tracking this down, I isolated it as far as setting SETSID to 1 during the Sbuild::Build phase. Attached is "wstopped.c" and "sbuild-poc" which tries to isolate the problem. With SETSID=0, I get the expected behavior; the process waits for SIGCONT: # perl /tmp/sbuild-poc /tmp/wstopped 0 ok With SETSID=1 (last cmdline option), the process does not wait for SIGCONT: # perl /tmp/sbuild-poc /tmp/wstopped 1 waitid: No child processes The bulk of wstopped.c is the creation of IPC pipes to make sure the child has started and the parent can wait on it. Very weird. Do you have any idea what is going on here? Thanks! -Kees -- Kees Cook @debian.org
#include <sys/types.h> #include <stdlib.h> #include <sys/wait.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> void test (void) { int fds[2]; if (pipe (fds) < 0) { perror ("pipe"); exit (1); } pid_t pid = fork (); if (pid < 0) { perror ("fork"); exit (1); } else if (pid == 0) { close (fds[0]); if (write (fds[1], "\n", 1) < 1) { perror ("write"); exit (1); } close (fds[1]); raise (SIGTSTP); exit (0); } else if (pid > 0) { char buf[1]; close (fds[1]); if (read (fds[0], buf, 1) < 1) { perror ("read"); exit (1); } close (fds[0]); siginfo_t info; if (waitid (P_PID, pid, &info, WSTOPPED | WNOWAIT) != 0) { perror ("waitid"); exit (1); } waitid (P_PID, pid, &info, WSTOPPED); if (kill (pid, SIGCONT) < 0) { perror ("kill"); exit (1); } int status; waitpid (pid, &status, 0); } } int main (int argc, char *argv[]) { test (); puts("ok"); return 0; }
#!/usr/bin/perl # Author: Kees Cook <k...@ubuntu.com> # # This shows a strange failure with raise(SIGTSTP) when SETSID=1 during # an sbuild run. # Build up a package similar to Sbuild::Build package Test::Build; use strict; use warnings; use Sbuild::Base; use Sbuild::ChrootRoot; use Sbuild::Conf; use Sbuild::Utility; BEGIN { use Exporter (); our (@ISA, @EXPORT); @ISA = qw(Exporter Sbuild::Base); @EXPORT = qw(); } sub new { my $class = shift; my $conf = Sbuild::Conf->new(); my $self = $class->SUPER::new($conf); bless($self, $class); return $self; } sub build { my $self = shift; my $cmd = shift; my $setsid = shift; $setsid += 0; my $session = Sbuild::ChrootRoot->new($self->get('Config')); $session->begin_session(); $self->set('Session', $session); my $buildenv = {}; $buildenv->{'PATH'} = '/bin:/usr/bin'; my $command = { COMMAND => [$cmd], ENV => $buildenv, SETSID => $setsid, CHROOT => 1, PRIORITY => 0, DIR => '/tmp' }; my $pipe = $self->get('Session')->pipe_command($command); while(<$pipe>) { $self->log($_); } close($pipe); } package main; my $test = Test::Build->new(); $test->build($ARGV[0], $ARGV[1]);