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: Ludovic Courtès
Subject: Re: Differences between container used by "guix build" and "guix environment -C -N"
Date: Sat, 01 Jul 2017 14:59:25 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux)

Hi,

Danny Milosavljevic <address@hidden> skribis:

> 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")

I guess the question would be whether ‘cmd.spawn’ relies on /bin/sh to
spawn processes, in which case “/bin/sh” would need patching like we do
for the ‘system’ function in libc and in other similar situations.  That
doesn’t seem to be the case at first sight.

Ludo’.



reply via email to

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