Skip to content

Commit d68b152

Browse files
committed
std: Be resilient to failure in pthread_getattr_np
This can fail on linux for various reasons, such as the /proc filesystem not being mounted. There are already many cases where we can't set up stack guards, so just don't worry about this case and communicate that no guard was enabled. I've confirmed that this allows the compiler to run in a chroot without /proc mounted. Closes #22642
1 parent 39d4faf commit d68b152

File tree

4 files changed

+60
-47
lines changed

4 files changed

+60
-47
lines changed

src/libstd/rt/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
9696
// own fault handlers if we hit it.
9797
sys_common::stack::record_os_managed_stack_bounds(my_stack_bottom,
9898
my_stack_top);
99-
sys::thread::guard::init();
99+
let main_guard = sys::thread::guard::init();
100100
sys::stack_overflow::init();
101101

102102
// Next, set up the current Thread with the guard information we just
103103
// created. Note that this isn't necessary in general for new threads,
104104
// but we just do this to name the main thread and to give it correct
105105
// info about the stack bounds.
106106
let thread: Thread = NewThread::new(Some("<main>".to_string()));
107-
thread_info::set(sys::thread::guard::main(), thread);
107+
thread_info::set(main_guard, thread);
108108

109109
// By default, some platforms will send a *signal* when a EPIPE error
110110
// would otherwise be delivered. This runtime doesn't install a SIGPIPE

src/libstd/sys/common/thread_info.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use thread::Thread;
1818
use thread::LocalKeyState;
1919

2020
struct ThreadInfo {
21-
stack_guard: usize,
21+
stack_guard: Option<usize>,
2222
thread: Thread,
2323
}
2424

@@ -33,7 +33,7 @@ impl ThreadInfo {
3333
THREAD_INFO.with(move |c| {
3434
if c.borrow().is_none() {
3535
*c.borrow_mut() = Some(ThreadInfo {
36-
stack_guard: 0,
36+
stack_guard: None,
3737
thread: NewThread::new(None),
3838
})
3939
}
@@ -47,10 +47,10 @@ pub fn current_thread() -> Option<Thread> {
4747
}
4848

4949
pub fn stack_guard() -> Option<usize> {
50-
ThreadInfo::with(|info| info.stack_guard)
50+
ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
5151
}
5252

53-
pub fn set(stack_guard: usize, thread: Thread) {
53+
pub fn set(stack_guard: Option<usize>, thread: Thread) {
5454
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
5555
THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
5656
stack_guard: stack_guard,

src/libstd/sys/unix/thread.rs

+50-38
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,10 @@ impl Drop for Thread {
166166
not(target_os = "netbsd"),
167167
not(target_os = "openbsd")))]
168168
pub mod guard {
169-
pub unsafe fn current() -> usize { 0 }
170-
pub unsafe fn main() -> usize { 0 }
171-
pub unsafe fn init() {}
169+
use prelude::v1::*;
170+
171+
pub unsafe fn current() -> Option<usize> { None }
172+
pub unsafe fn init() -> Option<usize> { None }
172173
}
173174

174175

@@ -179,6 +180,8 @@ pub mod guard {
179180
target_os = "openbsd"))]
180181
#[allow(unused_imports)]
181182
pub mod guard {
183+
use prelude::v1::*;
184+
182185
use libc::{self, pthread_t};
183186
use libc::funcs::posix88::mman::mmap;
184187
use libc::consts::os::posix88::{PROT_NONE,
@@ -191,31 +194,38 @@ pub mod guard {
191194
use super::{pthread_self, pthread_attr_destroy};
192195
use sys::os;
193196

194-
// These are initialized in init() and only read from after
195-
static mut GUARD_PAGE: usize = 0;
196-
197197
#[cfg(any(target_os = "macos",
198198
target_os = "bitrig",
199199
target_os = "netbsd",
200200
target_os = "openbsd"))]
201-
unsafe fn get_stack_start() -> *mut libc::c_void {
202-
current() as *mut libc::c_void
201+
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
202+
current().map(|s| s as *mut libc::c_void)
203203
}
204204

205205
#[cfg(any(target_os = "linux", target_os = "android"))]
206-
unsafe fn get_stack_start() -> *mut libc::c_void {
206+
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
207+
use super::pthread_attr_init;
208+
209+
let mut ret = None;
207210
let mut attr: libc::pthread_attr_t = mem::zeroed();
208-
assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
209-
let mut stackaddr = ptr::null_mut();
210-
let mut stacksize = 0;
211-
assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
211+
assert_eq!(pthread_attr_init(&mut attr), 0);
212+
if pthread_getattr_np(pthread_self(), &mut attr) == 0 {
213+
let mut stackaddr = ptr::null_mut();
214+
let mut stacksize = 0;
215+
assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr,
216+
&mut stacksize), 0);
217+
ret = Some(stackaddr);
218+
}
212219
assert_eq!(pthread_attr_destroy(&mut attr), 0);
213-
stackaddr
220+
ret
214221
}
215222

216-
pub unsafe fn init() {
223+
pub unsafe fn init() -> Option<usize> {
217224
let psize = os::page_size();
218-
let mut stackaddr = get_stack_start();
225+
let mut stackaddr = match get_stack_start() {
226+
Some(addr) => addr,
227+
None => return None,
228+
};
219229

220230
// Ensure stackaddr is page aligned! A parent process might
221231
// have reset RLIMIT_STACK to be non-page aligned. The
@@ -245,25 +255,21 @@ pub mod guard {
245255

246256
let offset = if cfg!(target_os = "linux") {2} else {1};
247257

248-
GUARD_PAGE = stackaddr as usize + offset * psize;
249-
}
250-
251-
pub unsafe fn main() -> usize {
252-
GUARD_PAGE
258+
Some(stackaddr as usize + offset * psize)
253259
}
254260

255261
#[cfg(target_os = "macos")]
256-
pub unsafe fn current() -> usize {
262+
pub unsafe fn current() -> Option<usize> {
257263
extern {
258264
fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void;
259265
fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t;
260266
}
261-
(pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
262-
pthread_get_stacksize_np(pthread_self())) as usize
267+
Some((pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
268+
pthread_get_stacksize_np(pthread_self())) as usize)
263269
}
264270

265271
#[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
266-
pub unsafe fn current() -> usize {
272+
pub unsafe fn current() -> Option<usize> {
267273
#[repr(C)]
268274
struct stack_t {
269275
ss_sp: *mut libc::c_void,
@@ -280,30 +286,36 @@ pub mod guard {
280286
assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0);
281287

282288
let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
283-
if pthread_main_np() == 1 {
289+
Some(if pthread_main_np() == 1 {
284290
// main thread
285291
current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
286292
} else {
287293
// new thread
288294
current_stack.ss_sp as usize - current_stack.ss_size as usize
289-
}
295+
})
290296
}
291297

292298
#[cfg(any(target_os = "linux", target_os = "android"))]
293-
pub unsafe fn current() -> usize {
299+
pub unsafe fn current() -> Option<usize> {
300+
use super::pthread_attr_init;
301+
302+
let mut ret = None;
294303
let mut attr: libc::pthread_attr_t = mem::zeroed();
295-
assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
296-
let mut guardsize = 0;
297-
assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
298-
if guardsize == 0 {
299-
panic!("there is no guard page");
304+
assert_eq!(pthread_attr_init(&mut attr), 0);
305+
if pthread_getattr_np(pthread_self(), &mut attr) == 0 {
306+
let mut guardsize = 0;
307+
assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
308+
if guardsize == 0 {
309+
panic!("there is no guard page");
310+
}
311+
let mut stackaddr = ptr::null_mut();
312+
let mut size = 0;
313+
assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
314+
315+
ret = Some(stackaddr as usize + guardsize as usize);
300316
}
301-
let mut stackaddr = ptr::null_mut();
302-
let mut size = 0;
303-
assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
304317
assert_eq!(pthread_attr_destroy(&mut attr), 0);
305-
306-
stackaddr as usize + guardsize as usize
318+
return ret
307319
}
308320

309321
#[cfg(any(target_os = "linux", target_os = "android"))]

src/libstd/sys/windows/thread.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ impl Thread {
8686
}
8787

8888
pub mod guard {
89-
pub unsafe fn main() -> usize { 0 }
90-
pub unsafe fn current() -> usize { 0 }
91-
pub unsafe fn init() {}
89+
use prelude::v1::*;
90+
91+
pub unsafe fn current() -> Option<usize> { None }
92+
pub unsafe fn init() -> Option<usize> { None }
9293
}

0 commit comments

Comments
 (0)