Skip to content

Commit 5a5c8c5

Browse files
committed
---
yaml --- r: 150356 b: refs/heads/try2 c: 68c2706 h: refs/heads/master v: v3
1 parent 171e589 commit 5a5c8c5

File tree

7 files changed

+130
-117
lines changed

7 files changed

+130
-117
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: fd4f15ea6b04fcacc8c8446c5d725c25daab0624
8+
refs/heads/try2: 68c2706780031e3aac6cccea0f7b867ad5eff13a
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libnative/io/process.rs

Lines changed: 23 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -134,18 +134,6 @@ impl rtio::RtioProcess for Process {
134134
}
135135

136136
fn kill(&mut self, signum: int) -> Result<(), io::IoError> {
137-
// On linux (and possibly other unices), a process that has exited will
138-
// continue to accept signals because it is "defunct". The delivery of
139-
// signals will only fail once the child has been reaped. For this
140-
// reason, if the process hasn't exited yet, then we attempt to collect
141-
// their status with WNOHANG.
142-
if self.exit_code.is_none() {
143-
match waitpid_nowait(self.pid) {
144-
Some(code) => { self.exit_code = Some(code); }
145-
None => {}
146-
}
147-
}
148-
149137
// if the process has finished, and therefore had waitpid called,
150138
// and we kill it, then on unix we might ending up killing a
151139
// newer process that happens to have the same (re-used) id
@@ -674,31 +662,6 @@ fn free_handle(_handle: *()) {
674662
// unix has no process handle object, just a pid
675663
}
676664

677-
#[cfg(unix)]
678-
fn translate_status(status: c_int) -> p::ProcessExit {
679-
#[cfg(target_os = "linux")]
680-
#[cfg(target_os = "android")]
681-
mod imp {
682-
pub fn WIFEXITED(status: i32) -> bool { (status & 0xff) == 0 }
683-
pub fn WEXITSTATUS(status: i32) -> i32 { (status >> 8) & 0xff }
684-
pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
685-
}
686-
687-
#[cfg(target_os = "macos")]
688-
#[cfg(target_os = "freebsd")]
689-
mod imp {
690-
pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
691-
pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 }
692-
pub fn WTERMSIG(status: i32) -> i32 { status & 0o177 }
693-
}
694-
695-
if imp::WIFEXITED(status) {
696-
p::ExitStatus(imp::WEXITSTATUS(status) as int)
697-
} else {
698-
p::ExitSignal(imp::WTERMSIG(status) as int)
699-
}
700-
}
701-
702665
/**
703666
* Waits for a process to exit and returns the exit code, failing
704667
* if there is no process with the specified id.
@@ -760,31 +723,33 @@ fn waitpid(pid: pid_t) -> p::ProcessExit {
760723
#[cfg(unix)]
761724
fn waitpid_os(pid: pid_t) -> p::ProcessExit {
762725
use std::libc::funcs::posix01::wait;
763-
let mut status = 0 as c_int;
764-
match retry(|| unsafe { wait::waitpid(pid, &mut status, 0) }) {
765-
-1 => fail!("unknown waitpid error: {}", super::last_error()),
766-
_ => translate_status(status),
767-
}
768-
}
769-
}
770726

771-
fn waitpid_nowait(pid: pid_t) -> Option<p::ProcessExit> {
772-
return waitpid_os(pid);
727+
#[cfg(target_os = "linux")]
728+
#[cfg(target_os = "android")]
729+
mod imp {
730+
pub fn WIFEXITED(status: i32) -> bool { (status & 0xff) == 0 }
731+
pub fn WEXITSTATUS(status: i32) -> i32 { (status >> 8) & 0xff }
732+
pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
733+
}
773734

774-
// This code path isn't necessary on windows
775-
#[cfg(windows)]
776-
fn waitpid_os(_pid: pid_t) -> Option<p::ProcessExit> { None }
735+
#[cfg(target_os = "macos")]
736+
#[cfg(target_os = "freebsd")]
737+
mod imp {
738+
pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
739+
pub fn WEXITSTATUS(status: i32) -> i32 { status >> 8 }
740+
pub fn WTERMSIG(status: i32) -> i32 { status & 0o177 }
741+
}
777742

778-
#[cfg(unix)]
779-
fn waitpid_os(pid: pid_t) -> Option<p::ProcessExit> {
780-
use std::libc::funcs::posix01::wait;
781743
let mut status = 0 as c_int;
782-
match retry(|| unsafe {
783-
wait::waitpid(pid, &mut status, libc::WNOHANG)
784-
}) {
785-
n if n == pid => Some(translate_status(status)),
786-
0 => None,
787-
n => fail!("unknown waitpid error `{}`: {}", n, super::last_error()),
744+
match retry(|| unsafe { wait::waitpid(pid, &mut status, 0) }) {
745+
-1 => fail!("unknown waitpid error: {}", super::last_error()),
746+
_ => {
747+
if imp::WIFEXITED(status) {
748+
p::ExitStatus(imp::WEXITSTATUS(status) as int)
749+
} else {
750+
p::ExitSignal(imp::WTERMSIG(status) as int)
751+
}
752+
}
788753
}
789754
}
790755
}

branches/try2/src/libnative/lib.rs

Lines changed: 18 additions & 0 deletions
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);

branches/try2/src/libstd/io/process.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,7 @@ impl Process {
331331
/// signals (SIGTERM/SIGKILL/SIGINT) are translated to `TerminateProcess`.
332332
///
333333
/// Additionally, a signal number of 0 can check for existence of the target
334-
/// process. Note, though, that on some platforms signals will continue to
335-
/// be successfully delivered if the child has exited, but not yet been
336-
/// reaped.
334+
/// process.
337335
pub fn kill(id: libc::pid_t, signal: int) -> IoResult<()> {
338336
LocalIo::maybe_raise(|io| io.kill(id, signal))
339337
}
@@ -344,16 +342,8 @@ impl Process {
344342
/// Sends the specified signal to the child process, returning whether the
345343
/// signal could be delivered or not.
346344
///
347-
/// Note that signal 0 is interpreted as a poll to check whether the child
348-
/// process is still alive or not. If an error is returned, then the child
349-
/// process has exited.
350-
///
351-
/// On some unix platforms signals will continue to be received after a
352-
/// child has exited but not yet been reaped. In order to report the status
353-
/// of signal delivery correctly, unix implementations may invoke
354-
/// `waitpid()` with `WNOHANG` in order to reap the child as necessary.
355-
///
356-
/// # Errors
345+
/// Note that this is purely a wrapper around libuv's `uv_process_kill`
346+
/// function.
357347
///
358348
/// If the signal delivery fails, the corresponding error is returned.
359349
pub fn signal(&mut self, signal: int) -> IoResult<()> {
@@ -843,17 +833,4 @@ mod tests {
843833
p.signal_kill().unwrap();
844834
assert!(!p.wait().success());
845835
})
846-
847-
iotest!(fn test_zero() {
848-
let mut p = sleeper();
849-
p.signal_kill().unwrap();
850-
for _ in range(0, 20) {
851-
if p.signal(0).is_err() {
852-
assert!(!p.wait().success());
853-
return
854-
}
855-
timer::sleep(100);
856-
}
857-
fail!("never saw the child go away");
858-
})
859836
}

branches/try2/src/libstd/libc.rs

Lines changed: 30 additions & 6 deletions
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;
@@ -2356,8 +2364,6 @@ pub mod consts {
23562364

23572365
pub static CLOCK_REALTIME: c_int = 0;
23582366
pub static CLOCK_MONOTONIC: c_int = 1;
2359-
2360-
pub static WNOHANG: c_int = 1;
23612367
}
23622368
pub mod posix08 {
23632369
}
@@ -2743,6 +2749,8 @@ pub mod consts {
27432749
use libc::types::os::arch::c95::{c_int, size_t};
27442750

27452751
pub static SIGTRAP : c_int = 5;
2752+
pub static SIGPIPE: c_int = 13;
2753+
pub static SIG_IGN: size_t = 1;
27462754

27472755
pub static GLOB_APPEND : c_int = 0x0001;
27482756
pub static GLOB_DOOFFS : c_int = 0x0002;
@@ -2804,8 +2812,6 @@ pub mod consts {
28042812

28052813
pub static CLOCK_REALTIME: c_int = 0;
28062814
pub static CLOCK_MONOTONIC: c_int = 4;
2807-
2808-
pub static WNOHANG: c_int = 1;
28092815
}
28102816
pub mod posix08 {
28112817
}
@@ -3140,6 +3146,8 @@ pub mod consts {
31403146
use libc::types::os::arch::c95::{c_int, size_t};
31413147

31423148
pub static SIGTRAP : c_int = 5;
3149+
pub static SIGPIPE: c_int = 13;
3150+
pub static SIG_IGN: size_t = 1;
31433151

31443152
pub static GLOB_APPEND : c_int = 0x0001;
31453153
pub static GLOB_DOOFFS : c_int = 0x0002;
@@ -3191,8 +3199,6 @@ pub mod consts {
31913199
pub static PTHREAD_CREATE_JOINABLE: c_int = 1;
31923200
pub static PTHREAD_CREATE_DETACHED: c_int = 2;
31933201
pub static PTHREAD_STACK_MIN: size_t = 8192;
3194-
3195-
pub static WNOHANG: c_int = 1;
31963202
}
31973203
pub mod posix08 {
31983204
}
@@ -3844,6 +3850,24 @@ pub mod funcs {
38443850
}
38453851
}
38463852

3853+
pub mod signal {
3854+
use libc::types::os::arch::c95::c_int;
3855+
use libc::types::os::common::posix01::sighandler_t;
3856+
3857+
#[cfg(not(target_os = "android"))]
3858+
extern {
3859+
pub fn signal(signum: c_int,
3860+
handler: sighandler_t) -> sighandler_t;
3861+
}
3862+
3863+
#[cfg(target_os = "android")]
3864+
extern {
3865+
#[link_name = "bsd_signal"]
3866+
pub fn signal(signum: c_int,
3867+
handler: sighandler_t) -> sighandler_t;
3868+
}
3869+
}
3870+
38473871
pub mod wait {
38483872
use libc::types::os::arch::c95::{c_int};
38493873
use libc::types::os::arch::posix88::{pid_t};

branches/try2/src/test/run-pass/core-run-destroy.rs

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ extern crate native;
2222
extern crate green;
2323
extern crate rustuv;
2424

25-
use std::io::Process;
26-
27-
macro_rules! succeed( ($e:expr) => (
28-
match $e { Ok(..) => {}, Err(e) => fail!("failure: {}", e) }
29-
) )
30-
3125
macro_rules! iotest (
3226
{ fn $name:ident() $b:block $($a:attr)* } => (
3327
mod $name {
@@ -59,29 +53,28 @@ fn start(argc: int, argv: **u8) -> int {
5953
}
6054

6155
iotest!(fn test_destroy_once() {
62-
let mut p = sleeper();
63-
match p.signal_exit() {
64-
Ok(()) => {}
65-
Err(e) => fail!("error: {}", e),
66-
}
67-
})
56+
#[cfg(not(target_os="android"))]
57+
static mut PROG: &'static str = "echo";
6858

69-
#[cfg(unix)]
70-
pub fn sleeper() -> Process {
71-
Process::new("sleep", [~"1000"]).unwrap()
72-
}
73-
#[cfg(windows)]
74-
pub fn sleeper() -> Process {
75-
// There's a `timeout` command on windows, but it doesn't like having
76-
// its output piped, so instead just ping ourselves a few times with
77-
// gaps inbetweeen so we're sure this process is alive for awhile
78-
Process::new("ping", [~"127.0.0.1", ~"-n", ~"1000"]).unwrap()
79-
}
59+
#[cfg(target_os="android")]
60+
static mut PROG: &'static str = "ls"; // android don't have echo binary
61+
62+
let mut p = unsafe {Process::new(PROG, []).unwrap()};
63+
p.signal_exit().unwrap(); // this shouldn't crash (and nor should the destructor)
64+
})
8065

8166
iotest!(fn test_destroy_twice() {
82-
let mut p = sleeper();
83-
succeed!(p.signal_exit()); // this shouldnt crash...
84-
let _ = p.signal_exit(); // ...and nor should this (and nor should the destructor)
67+
#[cfg(not(target_os="android"))]
68+
static mut PROG: &'static str = "echo";
69+
#[cfg(target_os="android")]
70+
static mut PROG: &'static str = "ls"; // android don't have echo binary
71+
72+
let mut p = match unsafe{Process::new(PROG, [])} {
73+
Ok(p) => p,
74+
Err(e) => fail!("wut: {}", e),
75+
};
76+
p.signal_exit().unwrap(); // this shouldnt crash...
77+
p.signal_exit().unwrap(); // ...and nor should this (and nor should the destructor)
8578
})
8679

8780
pub fn test_destroy_actually_kills(force: bool) {
Lines changed: 36 additions & 0 deletions
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)