Skip to content

Commit ca6af79

Browse files
committed
---
yaml --- r: 214271 b: refs/heads/auto c: cae0051 h: refs/heads/master i: 214269: 970b49e 214267: 05b882f 214263: 7088446 214255: 996fcde 214239: 9d7fa2c 214207: 8775eb0 214143: 361362f 214015: a9fdc68 v: v3
1 parent 2be6d43 commit ca6af79

File tree

4 files changed

+125
-3
lines changed

4 files changed

+125
-3
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
88
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
99
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1010
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
11-
refs/heads/auto: 56d904c4bb4a10e6da3f03d11279e9a3f3d20d8b
11+
refs/heads/auto: cae005162d1d7aea6cffdc299fedf0d2bb2a4b28
1212
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1313
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336
1414
refs/tags/0.2: 1754d02027f2924bed83b0160ee340c7f41d5ea1

branches/auto/src/libstd/sys/unix/c.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#![allow(non_camel_case_types)]
2626

2727
pub use self::signal_os::{sigaction, siginfo, sigset_t, sigaltstack};
28-
pub use self::signal_os::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSTKSZ};
28+
pub use self::signal_os::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSTKSZ, SIG_SETMASK};
2929

3030
use libc;
3131

@@ -112,6 +112,7 @@ pub struct passwd {
112112
pub type sighandler_t = *mut libc::c_void;
113113

114114
pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
115+
pub const SIG_ERR: sighandler_t = !0 as sighandler_t;
115116

116117
extern {
117118
pub fn getsockopt(sockfd: libc::c_int,
@@ -135,6 +136,8 @@ extern {
135136
oss: *mut sigaltstack) -> libc::c_int;
136137

137138
pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
139+
pub fn pthread_sigmask(how: libc::c_int, set: *const sigset_t,
140+
oldset: *mut sigset_t) -> libc::c_int;
138141

139142
#[cfg(not(target_os = "ios"))]
140143
pub fn getpwuid_r(uid: libc::uid_t,
@@ -155,7 +158,7 @@ extern {
155158
#[cfg(any(target_os = "linux",
156159
target_os = "android"))]
157160
mod signal_os {
158-
pub use self::arch::{SA_ONSTACK, SA_SIGINFO, SIGBUS,
161+
pub use self::arch::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_SETMASK,
159162
sigaction, sigaltstack};
160163
use libc;
161164

@@ -216,6 +219,8 @@ mod signal_os {
216219

217220
pub const SIGBUS: libc::c_int = 7;
218221

222+
pub const SIG_SETMASK: libc::c_int = 2;
223+
219224
#[cfg(target_os = "linux")]
220225
#[repr(C)]
221226
pub struct sigaction {
@@ -263,6 +268,8 @@ mod signal_os {
263268

264269
pub const SIGBUS: libc::c_int = 10;
265270

271+
pub const SIG_SETMASK: libc::c_int = 3;
272+
266273
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
267274
#[repr(C)]
268275
pub struct sigaction {
@@ -321,6 +328,8 @@ mod signal_os {
321328
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
322329
pub const SIGSTKSZ: libc::size_t = 40960;
323330

331+
pub const SIG_SETMASK: libc::c_int = 3;
332+
324333
#[cfg(any(target_os = "macos",
325334
target_os = "ios"))]
326335
pub type sigset_t = u32;

branches/auto/src/libstd/sys/unix/process.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use ffi::{OsString, OsStr, CString, CStr};
1717
use fmt;
1818
use io::{self, Error, ErrorKind};
1919
use libc::{self, pid_t, c_void, c_int, gid_t, uid_t};
20+
use mem;
2021
use ptr;
2122
use sys::fd::FileDesc;
2223
use sys::fs::{File, OpenOptions};
@@ -313,6 +314,23 @@ impl Process {
313314
if !envp.is_null() {
314315
*sys::os::environ() = envp as *const _;
315316
}
317+
318+
// Reset signal handling so the child process starts in a
319+
// standardized state. libstd ignores SIGPIPE, and signal-handling
320+
// libraries often set a mask. Child processes inherit ignored
321+
// signals and the signal mask from their parent, but most
322+
// UNIX programs do not reset these things on their own, so we
323+
// need to clean things up now to avoid confusing the program
324+
// we're about to run.
325+
let mut set: c::sigset_t = mem::uninitialized();
326+
if c::sigemptyset(&mut set) != 0 ||
327+
c::pthread_sigmask(c::SIG_SETMASK, &set, ptr::null_mut()) != 0 ||
328+
libc::funcs::posix01::signal::signal(
329+
libc::SIGPIPE, mem::transmute(c::SIG_DFL)
330+
) == mem::transmute(c::SIG_ERR) {
331+
fail(&mut output);
332+
}
333+
316334
let _ = libc::execvp(*argv, argv);
317335
fail(&mut output)
318336
}
@@ -418,3 +436,59 @@ fn translate_status(status: c_int) -> ExitStatus {
418436
ExitStatus::Signal(imp::WTERMSIG(status))
419437
}
420438
}
439+
440+
#[cfg(test)]
441+
mod tests {
442+
use super::*;
443+
use prelude::v1::*;
444+
445+
use ffi::OsStr;
446+
use mem;
447+
use ptr;
448+
use libc;
449+
use sys::{self, c, cvt, pipe};
450+
451+
extern {
452+
fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int;
453+
}
454+
455+
#[test]
456+
fn test_process_mask() {
457+
unsafe {
458+
// Test to make sure that a signal mask does not get inherited.
459+
let cmd = Command::new(OsStr::new("cat"));
460+
let (stdin_read, stdin_write) = sys::pipe::anon_pipe().unwrap();
461+
let (stdout_read, stdout_write) = sys::pipe::anon_pipe().unwrap();
462+
463+
let mut set: c::sigset_t = mem::uninitialized();
464+
let mut old_set: c::sigset_t = mem::uninitialized();
465+
cvt(c::sigemptyset(&mut set)).unwrap();
466+
cvt(sigaddset(&mut set, libc::SIGINT)).unwrap();
467+
cvt(c::pthread_sigmask(c::SIG_SETMASK, &set, &mut old_set)).unwrap();
468+
469+
let cat = Process::spawn(&cmd, Stdio::Raw(stdin_read.raw()),
470+
Stdio::Raw(stdout_write.raw()),
471+
Stdio::None).unwrap();
472+
drop(stdin_read);
473+
drop(stdout_write);
474+
475+
cvt(c::pthread_sigmask(c::SIG_SETMASK, &old_set, ptr::null_mut())).unwrap();
476+
477+
cvt(libc::funcs::posix88::signal::kill(cat.id() as libc::pid_t, libc::SIGINT)).unwrap();
478+
// We need to wait until SIGINT is definitely delivered. The
479+
// easiest way is to write something to cat, and try to read it
480+
// back: if SIGINT is unmasked, it'll get delivered when cat is
481+
// next scheduled.
482+
let _ = stdin_write.write(b"Hello");
483+
drop(stdin_write);
484+
485+
// Either EOF or failure (EPIPE) is okay.
486+
let mut buf = [0; 5];
487+
if let Ok(ret) = stdout_read.read(&mut buf) {
488+
assert!(ret == 0);
489+
}
490+
491+
cat.wait().unwrap();
492+
}
493+
}
494+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-android since the dynamic linker sets a SIGPIPE handler (to do
12+
// a crash report) so inheritance is moot on the entire platform
13+
14+
// libstd ignores SIGPIPE, and other libraries may set signal masks.
15+
// Make sure that these behaviors don't get inherited to children
16+
// spawned via std::process, since they're needed for traditional UNIX
17+
// filter behavior. This test checks that `yes | head` terminates
18+
// (instead of running forever), and that it does not print an error
19+
// message about a broken pipe.
20+
21+
use std::process;
22+
use std::thread;
23+
24+
#[cfg(unix)]
25+
fn main() {
26+
// Just in case `yes` doesn't check for EPIPE...
27+
thread::spawn(|| {
28+
thread::sleep_ms(5000);
29+
process::exit(1);
30+
});
31+
let output = process::Command::new("sh").arg("-c").arg("yes | head").output().unwrap();
32+
assert!(output.status.success());
33+
assert!(output.stderr.len() == 0);
34+
}
35+
36+
#[cfg(not(unix))]
37+
fn main() {
38+
// Not worried about signal masks on other platforms
39+
}

0 commit comments

Comments
 (0)