Skip to content

Commit af633ce

Browse files
committed
native: fix passing errno to parent after fork
The bitshifts were wrong in that they invoked undefined behavior and only passed the lower byte of the presumed-to-be-32bit errno value. Apparently all actually possible values for errno happen to be easily under 256, so this didn't cause any actual problems. This commit fixes the bitshifts, but doesn't generalize to errno types that aren't 32bit.
1 parent dd7f00d commit af633ce

File tree

2 files changed

+103
-8
lines changed

2 files changed

+103
-8
lines changed

src/libnative/io/process.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,11 @@ fn spawn_process_os(cfg: ProcessConfig,
583583
let mut bytes = [0, ..4];
584584
return match input.inner_read(bytes) {
585585
Ok(4) => {
586-
let errno = (bytes[0] << 24) as i32 |
587-
(bytes[1] << 16) as i32 |
588-
(bytes[2] << 8) as i32 |
589-
(bytes[3] << 0) as i32;
586+
let errno = (bytes[0] as i32 << 24) |
587+
(bytes[1] as i32 << 16) |
588+
(bytes[2] as i32 << 8) |
589+
(bytes[3] as i32 << 0);
590+
590591
Err(IoError {
591592
code: errno as uint,
592593
detail: None,
@@ -637,10 +638,10 @@ fn spawn_process_os(cfg: ProcessConfig,
637638
fn fail(output: &mut file::FileDesc) -> ! {
638639
let errno = os::errno();
639640
let bytes = [
640-
(errno << 24) as u8,
641-
(errno << 16) as u8,
642-
(errno << 8) as u8,
643-
(errno << 0) as u8,
641+
(errno >> 24) as u8,
642+
(errno >> 16) as u8,
643+
(errno >> 8) as u8,
644+
(errno >> 0) as u8,
644645
];
645646
assert!(output.inner_write(bytes).is_ok());
646647
unsafe { libc::_exit(1) }
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright 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-windows
12+
13+
#![feature(macro_rules)]
14+
15+
extern crate native;
16+
extern crate rustrt;
17+
extern crate libc;
18+
use libc::{c_char, c_int};
19+
use native::io::process;
20+
use rustrt::rtio;
21+
use rustrt::c_str;
22+
23+
macro_rules! c_string {
24+
($s:expr) => { {
25+
let ptr = concat!($s, "\0").as_ptr() as *const i8;
26+
unsafe { &c_str::CString::new(ptr, false) }
27+
} }
28+
}
29+
30+
static EXPECTED_ERRNO: c_int = 0x778899aa;
31+
32+
#[no_mangle]
33+
pub unsafe extern "C" fn chdir(_: *const c_char) -> c_int {
34+
// copied from std::os::errno()
35+
#[cfg(any(target_os = "macos",
36+
target_os = "ios",
37+
target_os = "freebsd"))]
38+
fn errno_location() -> *mut c_int {
39+
extern {
40+
fn __error() -> *mut c_int;
41+
}
42+
unsafe {
43+
__error()
44+
}
45+
}
46+
47+
#[cfg(target_os = "dragonfly")]
48+
fn errno_location() -> *mut c_int {
49+
extern {
50+
fn __dfly_error() -> *mut c_int;
51+
}
52+
unsafe {
53+
__dfly_error()
54+
}
55+
}
56+
57+
#[cfg(any(target_os = "linux", target_os = "android"))]
58+
fn errno_location() -> *mut c_int {
59+
extern {
60+
fn __errno_location() -> *mut c_int;
61+
}
62+
unsafe {
63+
__errno_location()
64+
}
65+
}
66+
67+
*errno_location() = EXPECTED_ERRNO;
68+
return -1;
69+
}
70+
71+
fn main() {
72+
let program = c_string!("true");
73+
let cwd = c_string!("whatever");
74+
let cfg = rtio::ProcessConfig {
75+
program: program,
76+
args: &[],
77+
env: None,
78+
cwd: Some(cwd),
79+
stdin: rtio::Ignored,
80+
stdout: rtio::Ignored,
81+
stderr: rtio::Ignored,
82+
extra_io: &[],
83+
uid: None,
84+
gid: None,
85+
detach: false
86+
};
87+
88+
match process::Process::spawn(cfg) {
89+
Ok(_) => { fail!("spawn() should have failled"); }
90+
Err(rtio::IoError { code: err, ..}) => {
91+
assert_eq!(err as c_int, EXPECTED_ERRNO);
92+
}
93+
};
94+
}

0 commit comments

Comments
 (0)