std: Prevent print panics when using TLS #29491

Merged
merged 1 commit into from Nov 6, 2015

Conversation

Projects
None yet
6 participants
Owner

alexcrichton commented Oct 31, 2015

Currently if a print happens while a thread is being torn down it may cause a
panic if the LOCAL_STDOUT TLS slot has been destroyed by that point. This adds a
guard to check and prints to the process stdout if that's the case (as we do for
if the slot is already borrowed).

Closes #29488

std: Prevent print panics when using TLS
Currently if a print happens while a thread is being torn down it may cause a
panic if the LOCAL_STDOUT TLS slot has been destroyed by that point. This adds a
guard to check and prints to the process stdout if that's the case (as we do for
if the slot is already borrowed).

Closes #29488
Collaborator

rust-highfive commented Oct 31, 2015

r? @brson

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

+ //
+ // If, however, the actual I/O causes an error, we do indeed panic.
+ let result = match LOCAL_STDOUT.state() {
+ LocalKeyState::Uninitialized |
@nagisa

nagisa Oct 31, 2015

Contributor

LOCAL_STDOUT.with would initialize data, so I think this branch should go together with the next arm.

EDIT: this is also fine, because if stdout ends up actually changed from the global default, it would also get initialised.

@alexcrichton

alexcrichton Oct 31, 2015

Owner

Yeah this branch could actually go either way, but I figured that we may as well avoid initializing TLS if we're not gonna use it anyway (e.g. as you also mentioned it'd just go to the same place regardless)

+ LocalKeyState::Destroyed => stdout().write_fmt(args),
+ LocalKeyState::Valid => {
+ LOCAL_STDOUT.with(|s| {
+ if s.borrow_state() == BorrowState::Unused {
@nagisa

nagisa Oct 31, 2015

Contributor

IMHO this should block waiting (using e.g. a spinlock) rather than falling back to global stdout.

@nagisa

nagisa Oct 31, 2015

Contributor

Ah, never mind me, this is fine, since there’s rarely a case where LOCAL_STDOUT happens to not be global stdout and two levels of locks isn’t really good.

@alexcrichton

alexcrichton Oct 31, 2015

Owner

Yeah and currently the only way that this can be in use is if the same thread is already printing (e.g. somewhere up on the stack someone called println!), so we can't actually wait for the resource to become available here because it never will.

This is akin to calling println! in a Display implementation.

Contributor

nagisa commented Oct 31, 2015

LGTM. Would r+.

Member

sfackler commented Oct 31, 2015

Do we still use LOCAL_STDOUT? Can we kill it instead?

Owner

alexcrichton commented Oct 31, 2015

@sfackler currently it's used to still capture the stdout of tests, but that's the only use that I know of.

Owner

alexcrichton commented Nov 5, 2015

ping r? @brson

Contributor

brson commented Nov 5, 2015

@bors r+

Contributor

bors commented Nov 5, 2015

📌 Commit 8588654 has been approved by brson

Contributor

bors commented Nov 6, 2015

⌛️ Testing commit 8588654 with merge 7512808...

bors added a commit that referenced this pull request Nov 6, 2015

Auto merge of #29491 - alexcrichton:avoid-stdio-tls, r=brson
Currently if a print happens while a thread is being torn down it may cause a
panic if the LOCAL_STDOUT TLS slot has been destroyed by that point. This adds a
guard to check and prints to the process stdout if that's the case (as we do for
if the slot is already borrowed).

Closes #29488

@bors bors merged commit 8588654 into rust-lang:master Nov 6, 2015

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details

@alexcrichton alexcrichton deleted the alexcrichton:avoid-stdio-tls branch Jan 21, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment