guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Differences between container used by "guix build" and "guix environ


From: Danny Milosavljevic
Subject: Re: Differences between container used by "guix build" and "guix environment -C -N"
Date: Mon, 19 Jun 2017 20:58:08 +0200

Hi Ludo,

it does pretty much the equvalent of this Python program, in Rust:

------------------------
#!/usr/bin/env python3

import os
import subprocess
import signal

signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT])

p = subprocess.Popen(["cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGINT])

os.kill(p.pid, signal.SIGINT)
stdout, stderr = p.communicate(b"hello\n", timeout=1)
assert stdout == b""
p.wait()
------------------------

The goal of it is to test this feature: Their "Popen" implementation uses 
something like spawnvp, only they have overwritten it in order to clear the 
signal mask for the child.

In Rust the test is:

------------------------------------------------------

    fn test_process_mask() {
        unsafe {
            // Test to make sure that a signal mask does not get inherited.
            let mut cmd = Command::new(OsStr::new("cat"));

            let mut set: libc::sigset_t = mem::uninitialized();
            let mut old_set: libc::sigset_t = mem::uninitialized();
            t!(cvt(libc::sigemptyset(&mut set)));
            t!(cvt(sigaddset(&mut set, libc::SIGINT)));
            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut 
old_set)));

            cmd.stdin(Stdio::MakePipe);
            cmd.stdout(Stdio::MakePipe);

            let (mut cat, mut pipes) = t!(cmd.spawn(Stdio::Null, true));
            let stdin_write = pipes.stdin.take().unwrap();
            let stdout_read = pipes.stdout.take().unwrap();

            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set,
                                         ptr::null_mut())));

            t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
            // We need to wait until SIGINT is definitely delivered. The
            // easiest way is to write something to cat, and try to read it
            // back: if SIGINT is unmasked, it'll get delivered when cat is
            // next scheduled.
            let _ = stdin_write.write(b"Hello");
            drop(stdin_write);

            // Either EOF or failure (EPIPE) is okay.
            let mut buf = [0; 5];
            if let Ok(ret) = stdout_read.read(&mut buf) {
                assert!(ret == 0);
            }

            t!(cat.wait());
        }

------------------------------------------------------

and the implementation that clears the mask is 
https://github.com/rust-lang/rust/blob/1.16.0/src/libstd/sys/unix/process/process_unix.rs#L144
 (line 144ff, bottom of "fn do_exec")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]