Auto merge of #48575 - ishitatsuyuki:unix-no-thread, r=alexcrichton
rustc_driver: get rid of the extra thread **Do not rollup** We can alter the stack size afterwards on Unix. Having a separate thread causes poor debugging experience when interrupting with signals. I have to get the backtrace of the all thread, as the main thread is waiting to join doing nothing else. This patch allows me to just run `bt` to get the desired backtrace.
This commit is contained in:
commit
5758c2dd14
@ -24,6 +24,7 @@
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(set_stdio)]
|
||||
#![feature(rustc_stack_internals)]
|
||||
|
||||
extern crate arena;
|
||||
extern crate getopts;
|
||||
@ -1467,16 +1468,56 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
|
||||
// Temporarily have stack size set to 16MB to deal with nom-using crates failing
|
||||
const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB
|
||||
|
||||
let mut cfg = thread::Builder::new().name("rustc".to_string());
|
||||
#[cfg(unix)]
|
||||
let spawn_thread = unsafe {
|
||||
// Fetch the current resource limits
|
||||
let mut rlim = libc::rlimit {
|
||||
rlim_cur: 0,
|
||||
rlim_max: 0,
|
||||
};
|
||||
if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
error!("in_rustc_thread: error calling getrlimit: {}", err);
|
||||
true
|
||||
} else if rlim.rlim_max < STACK_SIZE as libc::rlim_t {
|
||||
true
|
||||
} else {
|
||||
std::rt::deinit_stack_guard();
|
||||
rlim.rlim_cur = STACK_SIZE as libc::rlim_t;
|
||||
if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
error!("in_rustc_thread: error calling setrlimit: {}", err);
|
||||
std::rt::update_stack_guard();
|
||||
true
|
||||
} else {
|
||||
std::rt::update_stack_guard();
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: Hacks on hacks. If the env is trying to override the stack size
|
||||
// then *don't* set it explicitly.
|
||||
if env::var_os("RUST_MIN_STACK").is_none() {
|
||||
cfg = cfg.stack_size(STACK_SIZE);
|
||||
// We set the stack size at link time. See src/rustc/rustc.rs.
|
||||
#[cfg(windows)]
|
||||
let spawn_thread = false;
|
||||
|
||||
#[cfg(not(any(windows,unix)))]
|
||||
let spawn_thread = true;
|
||||
|
||||
// The or condition is added from backward compatibility.
|
||||
if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() {
|
||||
let mut cfg = thread::Builder::new().name("rustc".to_string());
|
||||
|
||||
// FIXME: Hacks on hacks. If the env is trying to override the stack size
|
||||
// then *don't* set it explicitly.
|
||||
if env::var_os("RUST_MIN_STACK").is_none() {
|
||||
cfg = cfg.stack_size(STACK_SIZE);
|
||||
}
|
||||
|
||||
let thread = cfg.spawn(f);
|
||||
thread.unwrap().join()
|
||||
} else {
|
||||
Ok(f())
|
||||
}
|
||||
|
||||
let thread = cfg.spawn(f);
|
||||
thread.unwrap().join()
|
||||
}
|
||||
|
||||
/// Get a list of extra command-line flags provided by the user, as strings.
|
||||
|
@ -73,3 +73,18 @@ fn lang_start<T: ::process::Termination + 'static>
|
||||
{
|
||||
lang_start_internal(&move || main().report(), argc, argv)
|
||||
}
|
||||
|
||||
/// Function used for reverting changes to the main stack before setrlimit().
|
||||
/// This is POSIX (non-Linux) specific and unlikely to be directly stabilized.
|
||||
#[unstable(feature = "rustc_stack_internals", issue = "0")]
|
||||
pub unsafe fn deinit_stack_guard() {
|
||||
::sys::thread::guard::deinit();
|
||||
}
|
||||
|
||||
/// Function used for resetting the main stack guard address after setrlimit().
|
||||
/// This is POSIX specific and unlikely to be directly stabilized.
|
||||
#[unstable(feature = "rustc_stack_internals", issue = "0")]
|
||||
pub unsafe fn update_stack_guard() {
|
||||
let main_guard = ::sys::thread::guard::init();
|
||||
::sys_common::thread_info::reset_guard(main_guard);
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ pub mod guard {
|
||||
pub unsafe fn init() -> Option<Guard> {
|
||||
None
|
||||
}
|
||||
pub unsafe fn deinit() {}
|
||||
}
|
||||
|
||||
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
|
||||
|
@ -91,4 +91,5 @@ pub mod guard {
|
||||
pub type Guard = !;
|
||||
pub unsafe fn current() -> Option<Guard> { None }
|
||||
pub unsafe fn init() -> Option<Guard> { None }
|
||||
pub unsafe fn deinit() {}
|
||||
}
|
||||
|
@ -209,6 +209,7 @@ pub mod guard {
|
||||
pub type Guard = Range<usize>;
|
||||
pub unsafe fn current() -> Option<Guard> { None }
|
||||
pub unsafe fn init() -> Option<Guard> { None }
|
||||
pub unsafe fn deinit() {}
|
||||
}
|
||||
|
||||
|
||||
@ -222,8 +223,8 @@ pub mod guard {
|
||||
#[cfg_attr(test, allow(dead_code))]
|
||||
pub mod guard {
|
||||
use libc;
|
||||
use libc::mmap;
|
||||
use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
|
||||
use libc::{mmap, mprotect};
|
||||
use libc::{PROT_NONE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
|
||||
use ops::Range;
|
||||
use sys::os;
|
||||
|
||||
@ -284,10 +285,10 @@ pub mod guard {
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn init() -> Option<Guard> {
|
||||
PAGE_SIZE = os::page_size();
|
||||
|
||||
let mut stackaddr = get_stack_start()?;
|
||||
// Precondition: PAGE_SIZE is initialized.
|
||||
unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
|
||||
assert!(PAGE_SIZE != 0);
|
||||
let stackaddr = get_stack_start()?;
|
||||
|
||||
// Ensure stackaddr is page aligned! A parent process might
|
||||
// have reset RLIMIT_STACK to be non-page aligned. The
|
||||
@ -296,10 +297,17 @@ pub mod guard {
|
||||
// page-aligned, calculate the fix such that stackaddr <
|
||||
// new_page_aligned_stackaddr < stackaddr + stacksize
|
||||
let remainder = (stackaddr as usize) % PAGE_SIZE;
|
||||
if remainder != 0 {
|
||||
stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder)
|
||||
as *mut libc::c_void;
|
||||
}
|
||||
Some(if remainder == 0 {
|
||||
stackaddr
|
||||
} else {
|
||||
((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn init() -> Option<Guard> {
|
||||
PAGE_SIZE = os::page_size();
|
||||
|
||||
let stackaddr = get_stack_start_aligned()?;
|
||||
|
||||
if cfg!(target_os = "linux") {
|
||||
// Linux doesn't allocate the whole stack right away, and
|
||||
@ -336,6 +344,26 @@ pub mod guard {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn deinit() {
|
||||
if !cfg!(target_os = "linux") {
|
||||
if let Some(stackaddr) = get_stack_start_aligned() {
|
||||
// Remove the protection on the guard page.
|
||||
// FIXME: we cannot unmap the page, because when we mmap()
|
||||
// above it may be already mapped by the OS, which we can't
|
||||
// detect from mmap()'s return value. If we unmap this page,
|
||||
// it will lead to failure growing stack size on platforms like
|
||||
// macOS. Instead, just restore the page to a writable state.
|
||||
// This ain't Linux, so we probably don't need to care about
|
||||
// execstack.
|
||||
let result = mprotect(stackaddr, PAGE_SIZE, PROT_READ | PROT_WRITE);
|
||||
|
||||
if result != 0 {
|
||||
panic!("unable to reset the guard page");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "bitrig",
|
||||
target_os = "openbsd",
|
||||
|
@ -46,4 +46,5 @@ pub mod guard {
|
||||
pub type Guard = !;
|
||||
pub unsafe fn current() -> Option<Guard> { None }
|
||||
pub unsafe fn init() -> Option<Guard> { None }
|
||||
pub unsafe fn deinit() {}
|
||||
}
|
||||
|
@ -96,4 +96,5 @@ pub mod guard {
|
||||
pub type Guard = !;
|
||||
pub unsafe fn current() -> Option<Guard> { None }
|
||||
pub unsafe fn init() -> Option<Guard> { None }
|
||||
pub unsafe fn deinit() {}
|
||||
}
|
||||
|
@ -50,3 +50,7 @@ pub fn set(stack_guard: Option<Guard>, thread: Thread) {
|
||||
thread,
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn reset_guard(stack_guard: Option<Guard>) {
|
||||
THREAD_INFO.with(move |c| c.borrow_mut().as_mut().unwrap().stack_guard = stack_guard);
|
||||
}
|
||||
|
@ -9,6 +9,16 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(link_args)]
|
||||
|
||||
// Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
|
||||
// for the rationale.
|
||||
#[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
|
||||
// We only build for msvc and gnu now, but we use a exhaustive condition here
|
||||
// so we can expect either the stack size to be set or the build fails.
|
||||
#[cfg_attr(all(windows, not(target_env = "msvc")), link_args = "-Wl,--stack,16777216")]
|
||||
// Also, don't forget to set this for rustdoc.
|
||||
extern {}
|
||||
|
||||
extern crate rustc_driver;
|
||||
|
||||
|
@ -8,6 +8,16 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(link_args)]
|
||||
// Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
|
||||
// for the rationale.
|
||||
#[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
|
||||
// We only build for msvc and gnu now, but we use a exhaustive condition here
|
||||
// so we can expect either the stack size to be set or the build fails.
|
||||
#[cfg_attr(all(windows, not(target_env = "msvc")), link_args = "-Wl,--stack,16777216")]
|
||||
// See src/rustc/rustc.rs for the corresponding rustc settings.
|
||||
extern {}
|
||||
|
||||
extern crate rustdoc;
|
||||
|
||||
fn main() { rustdoc::main() }
|
||||
|
Loading…
Reference in New Issue
Block a user