From mboxrd@z Thu Jan 1 00:00:00 1970 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 Message-ID: <20170619205808.4ec56691@scratchpost.org> References: <20170618144350.67710ce2@scratchpost.org> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:46341) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dN1sY-0007iu-AG for guix-devel@gnu.org; Mon, 19 Jun 2017 14:58:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dN1sV-0006vD-6q for guix-devel@gnu.org; Mon, 19 Jun 2017 14:58:26 -0400 In-Reply-To: <20170618144350.67710ce2@scratchpost.org> List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: guix-devel@gnu.org, ludo@gnu.org 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")