-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Retry on EINVAL from pthread_attr_setstacksize() #11885
Conversation
This looks great, thanks! We're generally trying to remove conditions, and I'd rather fail for now instead of silently going to the default stack size. We can see what this buys us down the road, but I would imagine that you've covered most use cases with rounding/clamping. One thing that I also wanted to take care of here was dealing with the What'll happen now is that if you request a stack size of Does that make sense? I may have wandered off a bit on some tangents... This is also is a problem for allocating green stacks, but that can be dealt with in a separate commit. |
No problem, I'll move it.
Cheers, I was looking for something like that.
I'll update the commit log.
I'll update it to to take the red zone into account. That makes RED_ZONE + PTHREAD_MIN_STACK the absolute lower limit, right? |
Yeah, you may have to make the |
Thanks! |
Does this fix #6233 too? |
Updated. PTAL?
It didn't but as of bnoordhuis/rust@b09dd90 it does. |
assert_eq!(pthread_attr_setdetachstate(&mut attr, | ||
PTHREAD_CREATE_JOINABLE), 0); | ||
|
||
// Reserve room for the red zone, the runtime's stack of last resort. | ||
let stack_size = cmp::max(stack, RED_ZONE + __pthread_get_minstack(&attr) as uint); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be a little uncomfortable going through dlopen
/dlsym
/dlclose
for all created threads. This would mean that all native task spawns would take these hits.
I'm not entirely sure, but is there a difference between PTHREAD_STACK_MIN and __pthread_get_minstack?
That being said, I would be very comfortable merging this without fixing #6233 just yet, but I would imagine that a solution to #6233 would likely involve using dlsym
to figure out if you can actually call it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be a little uncomfortable going through dlopen/dlsym/dlclose for all created threads. This would mean that all native task spawns would take these hits.
I suppose it would be possible to cache the result somewhere though that could blow up if someone gets creative with unloading libpthread.so, then loading it again..
I'm not entirely sure, but is there a difference between PTHREAD_STACK_MIN and __pthread_get_minstack?
The return value of __pthread_get_minstack() is PTHREAD_STACK_MIN plus whatever glibc needs for thread-local storage (which is not per se a fixed quantity.)
That being said, I would be very comfortable merging this without fixing #6233 just yet, but I would imagine that a solution to #6233 would likely involve using dlsym to figure out if you can actually call it.
I think so. You can't rely on __pthread_get_minstack() being there, it was added in glibc 2.15. Most distros ship older versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, let's merge this and then we can see how big the impact is.
This'll also need a rebase on top of the current master before merging. |
Rebased. |
use option; | ||
use result::{Err, Ok}; | ||
use unstable::dynamic_lib; | ||
match dynamic_lib::DynamicLibrary::open(option::None) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistically, it'd be better to import option::None
and then use None
here.
Updated and rebased. I've added a comment about how the dlopen/dlsym/dlclose hit can be avoided if/when Rust grows weak symbol support. (Assuming it's not already there; I couldn't find anything to that effect.) |
@alexcrichton Are the failures related to my changes? It doesn't look like it but... |
It's failed twice in the same way, which seems suspicious. Once more for luck. |
This is suspicious, and I don't understand why this is happening. I'm building locally in hope that I can reproduce it |
Hm, I couldn't reproduce this at stage0/1/2 on my local mac. I've seen a number of "failure to unwind" failures on the bots recently, so this may just be unlucky. |
The flakiness may be fixed by #11947 |
Represents the minimum size of a thread's stack. As such, it's both platform and architecture-specific. I put it under posix01 even though it predates POSIX.1-2001 by some years. I believe it was first formalized in SUSv2. I doubt anyone cares, though.
Enforce that the stack size is > RED_ZONE + PTHREAD_STACK_MIN. If the call to pthread_attr_setstacksize() subsequently fails with EINVAL, it means that the platform requires the stack size to be a multiple of the page size. In that case, round up to the nearest page and retry. Fixes #11694.
glibc >= 2.15 has a __pthread_get_minstack() function that returns PTHREAD_STACK_MIN plus however many bytes are needed for thread-local storage. Use it when it's available because just PTHREAD_STACK_MIN is not enough in applications that have big thread-local storage requirements. Fixes #6233.
Rebased against master. I can confirm that i686-darwin-apple works okay locally for me. Can you give it one more try? |
EINVAL means that the requested stack size is either not a multiple of the system page size or that it's smaller than PTHREAD_STACK_MIN. Figure out what the case is, fix it up and retry. If it still fails, give up, like before. Suggestions for future improvements: * don't fail!() but instead signal a condition, or * silently ignore the error and use a default sized stack. Fixes #11694. The first two commits put the framework in place, the third one contains the meat.
EINVAL means that the requested stack size is either not a multiple
of the system page size or that it's smaller than PTHREAD_STACK_MIN.
Figure out what the case is, fix it up and retry. If it still fails,
give up, like before.
Suggestions for future improvements:
Fixes #11694.
The first two commits put the framework in place, the third one contains the meat.