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]);

Reply via email to