Skip to content

rustc_driver: get rid of the extra thread - #48575

Merged
bors merged 10 commits into
rust-lang:masterfrom
ishitatsuyuki:unix-no-thread
Apr 4, 2018
Merged

rustc_driver: get rid of the extra thread#48575
bors merged 10 commits into
rust-lang:masterfrom
ishitatsuyuki:unix-no-thread

Conversation

@ishitatsuyuki

@ishitatsuyukiishitatsuyuki commented Feb 27, 2018

Copy link
Copy Markdown
Contributor

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.

@rust-highfive

Copy link
Copy Markdown
Contributor

r? @petrochenkov

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfiverust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 27, 2018
@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

r? @alexcrichton

@alexcrichtonalexcrichton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I'm a little worried about the portability here but I think we can manage it where a slice of cases can be optimized to not use a separate thread

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be rlimit_stack?

Are you also sure this works on all Unix platforms?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, typo. rlimit is a POSIX standard, so it should.

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the rlim_max is too small, shouldnt a thread be spawned?

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this env var is set shouldn't a thread be spawned?

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a Windows solution be explored as well? It looks like the stack size can be configured in the executable headers as there is an msvc linker flag for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Do you know a way to pass custom linker flags? It doesn't seem to be supported in build scripts.

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs #[cfg(unix)].

Or combine the two functions in the form:

pubfnin_rustc_thread(...){constSTACK_SIZE:usize = 16*1048576;#[cfg(not(unix))]{// use threads}#[cfg(unix)]{// use rlimits}}

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this FIXME applies to the new code.

@ishitatsuyuki
ishitatsuyukiforce-pushed the unix-no-thread branch 2 times, most recently from 95d750d to b11df43CompareFebruary 27, 2018 10:30
@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

r? @alexcrichton

I think I've addressed all the review comments except support for Windows. As I said inline, I couldn't figure out how I can pass the /STACK link flag.

I guess it's OK because it compiles, but can you also check if I'm doing inline attributes correctly?

@alexcrichtonalexcrichton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a comment be added to the code as well to indicate why we're sometimes spawning a thread and sometimes not?

For Windows it looks like we'll want to pass -Wl,--stack,N on MinGW and /STACK:N on MSVC. Perhaps an unstable crate attribute could be added to src/rustc/rustc.rs?

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If setrlimit fails perhaps an info! log statement could be done but we fall back to spawning a thread? I don't personally know the situations where setrlimit can fail but it seems like one of those APIs that fails in obscure circumstances.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to manual there's no way the current implementation can fail, and thus if we detected an error it's either an OS bug or logic bug of this rlimit setting code.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately though in practice "POSIX says X" or "the manual says this can't fail" rarely holds up. Functions fail for mysterious reasons that aren't always strictly documented. I think it's best to try to head off any regressions and just fall back to spawning a thread here.

Comment threadsrc/librustc_driver/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be checked earlier? If this env var is set I think we'll want to force spawning a thread.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree: that environment variable only affects stack size of non-main thread. If we can extend the main thread stack, that's all what we need.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without moving this check earlier it's breaking existing behavior. Today the stack size of the rustc thread can be controlled by configuring RUST_MIN_STACK (can be useful for debugging). This commit breaks that ability because setrlimit will probably succeed on Linux.

@ishitatsuyukiishitatsuyuki added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 27, 2018
@ishitatsuyuki
ishitatsuyukiforce-pushed the unix-no-thread branch 2 times, most recently from c012840 to 472fc3fCompareMarch 4, 2018 01:30
@ishitatsuyukiishitatsuyuki changed the title rustc_driver: get rid of extra thread on Unixrustc_driver: get rid of the extra threadMar 6, 2018
Comment threadsrc/rustc/rustc.rs Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The /STACK option sets the size of the stack in bytes.

16384 bytes seems rather small.

@ishitatsuyukiishitatsuyuki added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 6, 2018
@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

r? @alexcrichton

I think I have addressed the concerns, and I have also added linker flags for Windows (didn't test on Windows). Also I no longer attempt to setrlimit as it doesn't refresh stack guard configuration.

Additionally, I modified the CI script to the CI runs benefit from this change.

@alexcrichton

Copy link
Copy Markdown
Member

Oh hm isn't this missing the point of the original PR now though? Wasn't the intention to avoid the main thread for debugging and such by default?

@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

Unfortunately setting rlimit after initialization isn't a safe stuff, and instead we now provide a way to get rid of it if the rlimit is configured by the user.

Maybe this can be documented somewhere else, but well, we can now achieve the ideal debugging experience by putting one line of shell configuration.

@alexcrichton

Copy link
Copy Markdown
Member

Ah sorry I'm not too familiar with setrlimit, but what makes it unsafe to extend the main stack?

@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

Extending the main stack breaks our stack guard page detection. Basically, when you extend the main stack after initialization, the page address stored in the SEGV handler becomes obsolete and we can no longer handle stack overflow as panic.

(What we do with stack guard changed a few times, and although currently it isn't UB it's very likely to cause unwanted behavior.)

@alexcrichton

Copy link
Copy Markdown
Member

Ah ok thanks for the clarification. That strategy though sounded like a pretty good one to me, so maybe an unstable API could be added to libstd for "reset stack guard detection of this thread"?

@ishitatsuyukiishitatsuyuki added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 8, 2018
@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

Partially addressed the Windows issues. Though, the default stack size is 1MB on Windows so it's more likely to affect users with clippy.

It's possible to get the stack size, but it is rather complicated:
https://github.com/mozilla/gecko-dev/blob/9bfc0167075b756824a1f6654a5a5cc03bba4f10/js/xpconnect/src/XPCJSContext.cpp

@alexcrichton

Copy link
Copy Markdown
Member

Looks like CI may be failing?

@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

@alexcrichton Fixed.

@alexcrichton

Copy link
Copy Markdown
Member

@bors: r+

@bors

bors commented Apr 3, 2018

Copy link
Copy Markdown
Collaborator

📌 Commit 7db854b has been approved by alexcrichton

@borsbors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 3, 2018
@bors

bors commented Apr 4, 2018

Copy link
Copy Markdown
Collaborator

⌛ Testing commit 7db854b with merge 5758c2d...

bors added a commit that referenced this pull request Apr 4, 2018
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.
@bors

bors commented Apr 4, 2018

Copy link
Copy Markdown
Collaborator

☀️ Test successful - status-appveyor, status-travis
Approved by: alexcrichton
Pushing 5758c2d to master...

@bors
bors merged commit 7db854b into rust-lang:masterApr 4, 2018
@eddyb

Copy link
Copy Markdown
Contributor

I wish this was discussed by the compiler team... there are several issues with the approach and I do not believe the motivation is sufficient (debuggers are usually necessary only for LLVM aborts).

It's unsound to not spawn a dedicated thread for the compiler because we can't correctly control thread-local resources - ideally they would be allocated in the parent thread, enforcing the fact that other thread-local data cannot possibly use-after-free the resources in their own destructors.

cc @rust-lang/compiler

bors added a commit that referenced this pull request Apr 28, 2018
rustc_driver: Catch ICEs on the main thread too
#48575 introduced an optimization to run rustc directly on the main thread when possible. However, the threaded code detects panics when they `join()` to report as an ICE. When running directly, we need to use `panic::catch_unwind` to get the same effect.
cc @ishitatsuyuki
r? @alexcrichton
@ishitatsuyuki
ishitatsuyuki deleted the unix-no-thread branch July 15, 2018 13:26
@nagisa

Copy link
Copy Markdown
Member

There’s one more potential reason to revert this: #52577.

@pnkfelix

Copy link
Copy Markdown
Contributor

@ishitatsuyuki would putting this mode under a -Z flag suffice for your purposes?

@ishitatsuyuki

Copy link
Copy Markdown
ContributorAuthor

Yes, as it's not really critical.

@pnkfelixpnkfelix mentioned this pull request Oct 4, 2018
@oli-obkoli-obk mentioned this pull request Dec 14, 2018
bors added a commit that referenced this pull request Dec 21, 2018
Always run rustc in a thread
cc @ishitatsuyuki@eddyb
r? @pnkfelix
[Previously](#48575) we moved to only producing threads when absolutely necessary. Even before we opted to only create threads in some cases, which [is unsound](#48575 (comment)) due to the way we use thread local storage.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-borsStatus: Waiting on bors to run and complete tests. Bors will change the label on completion.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

13 participants

@ishitatsuyuki@rust-highfive@alexcrichton@bors@Zoxc@retep998@eddyb@nagisa@pnkfelix@cuviper@kennytm@nikomatsakis@petrochenkov