Skip to content

Commit 42e1003

Browse files
committed
auto merge of #13158 : alexcrichton/rust/issue-13123, r=brson
Some unix platforms will send a SIGPIPE signal instead of returning EPIPE from a syscall by default. The native runtime doesn't install a SIGPIPE handler, causing the program to die immediately in this case. This brings the behavior in line with libgreen by ignoring SIGPIPE and propagating EPIPE upwards to the application in the form of an IoError. Closes #13123
2 parents fd4f15e + 68c2706 commit 42e1003

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

src/libnative/lib.rs

+18
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
9797
// frames above our current position.
9898
let my_stack_bottom = my_stack_top + 20000 - OS_DEFAULT_STACK_ESTIMATE;
9999

100+
// When using libgreen, one of the first things that we do is to turn off
101+
// the SIGPIPE signal (set it to ignore). By default, some platforms will
102+
// send a *signal* when a EPIPE error would otherwise be delivered. This
103+
// runtime doesn't install a SIGPIPE handler, causing it to kill the
104+
// program, which isn't exactly what we want!
105+
//
106+
// Hence, we set SIGPIPE to ignore when the program starts up in order to
107+
// prevent this problem.
108+
#[cfg(windows)] fn ignore_sigpipe() {}
109+
#[cfg(unix)] fn ignore_sigpipe() {
110+
use std::libc;
111+
use std::libc::funcs::posix01::signal::signal;
112+
unsafe {
113+
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
114+
}
115+
}
116+
ignore_sigpipe();
117+
100118
rt::init(argc, argv);
101119
let mut exit_code = None;
102120
let mut main = Some(main);

src/libstd/libc.rs

+30
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ pub mod types {
266266
}
267267

268268
pub enum timezone {}
269+
270+
pub type sighandler_t = size_t;
269271
}
270272
pub mod bsd44 {
271273
use libc::types::os::arch::c95::{c_char, c_int, c_uint};
@@ -637,6 +639,8 @@ pub mod types {
637639
}
638640

639641
pub enum timezone {}
642+
643+
pub type sighandler_t = size_t;
640644
}
641645
pub mod bsd44 {
642646
use libc::types::os::arch::c95::{c_char, c_int, c_uint};
@@ -1206,6 +1210,8 @@ pub mod types {
12061210
}
12071211

12081212
pub enum timezone {}
1213+
1214+
pub type sighandler_t = size_t;
12091215
}
12101216

12111217
pub mod bsd44 {
@@ -2292,6 +2298,8 @@ pub mod consts {
22922298
use libc::types::os::arch::c95::{c_int, size_t};
22932299

22942300
pub static SIGTRAP : c_int = 5;
2301+
pub static SIGPIPE: c_int = 13;
2302+
pub static SIG_IGN: size_t = 1;
22952303

22962304
pub static GLOB_ERR : c_int = 1 << 0;
22972305
pub static GLOB_MARK : c_int = 1 << 1;
@@ -2743,6 +2751,8 @@ pub mod consts {
27432751
use libc::types::os::arch::c95::{c_int, size_t};
27442752

27452753
pub static SIGTRAP : c_int = 5;
2754+
pub static SIGPIPE: c_int = 13;
2755+
pub static SIG_IGN: size_t = 1;
27462756

27472757
pub static GLOB_APPEND : c_int = 0x0001;
27482758
pub static GLOB_DOOFFS : c_int = 0x0002;
@@ -3140,6 +3150,8 @@ pub mod consts {
31403150
use libc::types::os::arch::c95::{c_int, size_t};
31413151

31423152
pub static SIGTRAP : c_int = 5;
3153+
pub static SIGPIPE: c_int = 13;
3154+
pub static SIG_IGN: size_t = 1;
31433155

31443156
pub static GLOB_APPEND : c_int = 0x0001;
31453157
pub static GLOB_DOOFFS : c_int = 0x0002;
@@ -3844,6 +3856,24 @@ pub mod funcs {
38443856
}
38453857
}
38463858

3859+
pub mod signal {
3860+
use libc::types::os::arch::c95::c_int;
3861+
use libc::types::os::common::posix01::sighandler_t;
3862+
3863+
#[cfg(not(target_os = "android"))]
3864+
extern {
3865+
pub fn signal(signum: c_int,
3866+
handler: sighandler_t) -> sighandler_t;
3867+
}
3868+
3869+
#[cfg(target_os = "android")]
3870+
extern {
3871+
#[link_name = "bsd_signal"]
3872+
pub fn signal(signum: c_int,
3873+
handler: sighandler_t) -> sighandler_t;
3874+
}
3875+
}
3876+
38473877
pub mod wait {
38483878
use libc::types::os::arch::c95::{c_int};
38493879
use libc::types::os::arch::posix88::{pid_t};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2012-2014 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-fast
12+
13+
// Be sure that when a SIGPIPE would have been received that the entire process
14+
// doesn't die in a ball of fire, but rather it's gracefully handled.
15+
16+
use std::os;
17+
use std::io::{PipeStream, Process};
18+
19+
fn test() {
20+
let os::Pipe { input, out } = os::pipe();
21+
let input = PipeStream::open(input);
22+
let mut out = PipeStream::open(out);
23+
drop(input);
24+
25+
let _ = out.write([1]);
26+
}
27+
28+
fn main() {
29+
let args = os::args();
30+
if args.len() > 1 && args[1].as_slice() == "test" {
31+
return test();
32+
}
33+
34+
let mut p = Process::new(args[0], [~"test"]).unwrap();
35+
assert!(p.wait().success());
36+
}

0 commit comments

Comments
 (0)