-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Don't use posix_spawn_file_actions_addchdir_np on macOS. #80537
Conversation
r? @dtolnay (rust-highfive has picked a reviewer for you, use r? to override) |
The bug is in |
Interesting, thanks for taking a look! Comments like "We hope that the race for a stat() is unimportant." are great. I guess another option in theory we could use Also, to be clear, I'm fine with the "do nothing" option. It just seems like an easy footgun, and there doesn't seem to be a clear path forward for #37868, which if it used an absolute path I think would fix this. I'm not sure I understood the discussion about A question is, are people willing to change the semantics of |
The macOS bug is quite severe when combined with |
a6a605b
to
69a93fc
Compare
OK, I have added a test. I think it should pass on all platforms, but I am not absolutely certain about some of the more unusual platforms (I tested linux, macos, and windows). |
@bors r+ |
📌 Commit 69a93fc86e7dc3e53b27d448de7e5e3e693d8c00 has been approved by |
⌛ Testing commit 69a93fc86e7dc3e53b27d448de7e5e3e693d8c00 with merge 21fd9891c3033f3ded7aa9e56ed16de03ab7779d... |
The job Click to see the possible cause of the failure (guessed by this bot)
|
💔 Test failed - checks-actions |
remote-test-server does not set the current_dir, and leaves it as `/`.
69a93fc
to
6e467b7
Compare
I pushed a small fix to make the test work on Android. An alternative fix would be to change remote-test-server to set the current_dir when it spawns a test, but I figure just updating the test would make it more robust. @bors r=dtolnay |
📌 Commit 6e467b7 has been approved by |
☀️ Test successful - checks-actions |
This is a complete rewrite `posix/runProcess.c`. There are a few goals of this rewrite: * fix a long-standing and serious bug in the `execvpe` fallback path, which uses non-reentrant functions after `fork`ing. This is of course undefined behavior and has been causing failures under Darwin's Rosetta binary translation engine (see GHC #19994). * eliminate code duplication in the `fork/exec` implementation. * introduce support for `posix_spawn`, allowing us to unload a significant amount of complexity in some cases. This is particularly desireable as the cost of `fork` has increased considerably in some cases on recent Darwin releases (namely when `MAP_JIT` mappings are used; see [1]) While `posix_spawn` is often a win, there are unfortunately several cases where it cannot be used: * `posix_spawn_file_actions_addchdir_np` is broken on Darwin * `POSIX_SPAWN_SETSID` is only supported on mac 10.15 and later, but doesn't return a proper error code when not supported * the originally-specified semantics of `posix_spawn_file_actions_adddup2` are unsafe and have been amended (see [3]) but not all implementations have caught up (musl has [4], glibc did later [5], Darwin seemingly hasn't) there appears to be no support at all for setuid and setgid * `spawn` is significantly slower than fork on some Darwin releases (see [6]) To address this we first try using `posix_spawn`, falling back on `fork/exec` if we encounter a case which the former cannot handle. [1]: libuv/libuv#3064 [2]: https://www.austingroupbugs.net/view.php?id=411 [3]: rust-lang/rust#80537 [4]: https://git.musl-libc.org/cgit/musl/commit/?id=6fc6ca1a323bc0b6b9e9cdc8fa72221ae18fe206 [5]: https://sourceware.org/bugzilla/show_bug.cgi?id=23640 [6]: https://discuss.python.org/t/multiprocessing-spawn-default-on-macos-since-python-3-8-is-slower-than-fork-method/5910/4
This is a complete rewrite `posix/runProcess.c`. There are a few goals of this rewrite: * fix a long-standing and serious bug in the `execvpe` fallback path, which uses non-reentrant functions after `fork`ing. This is of course undefined behavior and has been causing failures under Darwin's Rosetta binary translation engine (see GHC #19994). * eliminate code duplication in the `fork/exec` implementation. * introduce support for `posix_spawn`, allowing us to unload a significant amount of complexity in some cases. This is particularly desireable as the cost of `fork` has increased considerably in some cases on recent Darwin releases (namely when `MAP_JIT` mappings are used; see [1]) While `posix_spawn` is often a win, there are unfortunately several cases where it cannot be used: * `posix_spawn_file_actions_addchdir_np` is broken on Darwin * `POSIX_SPAWN_SETSID` is only supported on mac 10.15 and later, but doesn't return a proper error code when not supported * the originally-specified semantics of `posix_spawn_file_actions_adddup2` are unsafe and have been amended (see [3]) but not all implementations have caught up (musl has [4], glibc did later [5], Darwin seemingly hasn't) there appears to be no support at all for setuid and setgid * `spawn` is significantly slower than fork on some Darwin releases (see [6]) To address this we first try using `posix_spawn`, falling back on `fork/exec` if we encounter a case which the former cannot handle. [1]: libuv/libuv#3064 [2]: https://www.austingroupbugs.net/view.php?id=411 [3]: rust-lang/rust#80537 [4]: https://git.musl-libc.org/cgit/musl/commit/?id=6fc6ca1a323bc0b6b9e9cdc8fa72221ae18fe206 [5]: https://sourceware.org/bugzilla/show_bug.cgi?id=23640 [6]: https://discuss.python.org/t/multiprocessing-spawn-default-on-macos-since-python-3-8-is-slower-than-fork-method/5910/4
This is a complete rewrite `posix/runProcess.c`. There are a few goals of this rewrite: * fix a long-standing and serious bug in the `execvpe` fallback path, which uses non-reentrant functions after `fork`ing. This is of course undefined behavior and has been causing failures under Darwin's Rosetta binary translation engine (see GHC #19994). * eliminate code duplication in the `fork/exec` implementation. * introduce support for `posix_spawn`, allowing us to unload a significant amount of complexity in some cases. This is particularly desireable as the cost of `fork` has increased considerably in some cases on recent Darwin releases (namely when `MAP_JIT` mappings are used; see [1]) While `posix_spawn` is often a win, there are unfortunately several cases where it cannot be used: * `posix_spawn_file_actions_addchdir_np` is broken on Darwin * `POSIX_SPAWN_SETSID` is only supported on mac 10.15 and later, but doesn't return a proper error code when not supported * the originally-specified semantics of `posix_spawn_file_actions_adddup2` are unsafe and have been amended (see [3]) but not all implementations have caught up (musl has [4], glibc did later [5], Darwin seemingly hasn't) there appears to be no support at all for setuid and setgid * `spawn` is significantly slower than fork on some Darwin releases (see [6]) To address this we first try using `posix_spawn`, falling back on `fork/exec` if we encounter a case which the former cannot handle. [1]: libuv/libuv#3064 [2]: https://www.austingroupbugs.net/view.php?id=411 [3]: rust-lang/rust#80537 [4]: https://git.musl-libc.org/cgit/musl/commit/?id=6fc6ca1a323bc0b6b9e9cdc8fa72221ae18fe206 [5]: https://sourceware.org/bugzilla/show_bug.cgi?id=23640 [6]: https://discuss.python.org/t/multiprocessing-spawn-default-on-macos-since-python-3-8-is-slower-than-fork-method/5910/4
Currently, on macOS, Rust never uses the fast posix_spawn path if a directory change is requested due to a bug in Apple's libc. However, the bug is only triggered if the program is a relative path. This PR makes it so that the fast path continues to work if the program is an absolute path or a lone filename. This was an alternative proposed in rust-lang#80537 (comment), and it makes a measurable performance difference in some of my code that spawns thousands of processes.
…howers Use posix_spawn for absolute paths on macOS Currently, on macOS, Rust never uses the fast posix_spawn path if a directory change is requested, due to a bug in Apple's libc. However, the bug is only triggered if the program is a relative path. This PR makes it so that the fast path continues to work if the program is an absolute path or a lone filename. This was an alternative proposed in rust-lang#80537 (comment), and it makes a measurable performance difference in some of my code that spawns thousands of processes.
Currently, on macOS, Rust never uses the fast posix_spawn path if a directory change is requested due to a bug in Apple's libc. However, the bug is only triggered if the program is a relative path. This PR makes it so that the fast path continues to work if the program is an absolute path or a lone filename. This was an alternative proposed in rust-lang/rust#80537 (comment), and it makes a measurable performance difference in some of my code that spawns thousands of processes.
Use posix_spawn for absolute paths on macOS Currently, on macOS, Rust never uses the fast posix_spawn path if a directory change is requested, due to a bug in Apple's libc. However, the bug is only triggered if the program is a relative path. This PR makes it so that the fast path continues to work if the program is an absolute path or a lone filename. This was an alternative proposed in rust-lang/rust#80537 (comment), and it makes a measurable performance difference in some of my code that spawns thousands of processes.
Use posix_spawn for absolute paths on macOS Currently, on macOS, Rust never uses the fast posix_spawn path if a directory change is requested, due to a bug in Apple's libc. However, the bug is only triggered if the program is a relative path. This PR makes it so that the fast path continues to work if the program is an absolute path or a lone filename. This was an alternative proposed in rust-lang/rust#80537 (comment), and it makes a measurable performance difference in some of my code that spawns thousands of processes.
Use posix_spawn for absolute paths on macOS Currently, on macOS, Rust never uses the fast posix_spawn path if a directory change is requested, due to a bug in Apple's libc. However, the bug is only triggered if the program is a relative path. This PR makes it so that the fast path continues to work if the program is an absolute path or a lone filename. This was an alternative proposed in rust-lang/rust#80537 (comment), and it makes a measurable performance difference in some of my code that spawns thousands of processes.
There is a bug on macOS where using
posix_spawn_file_actions_addchdir_np
with a relative executable path will causeposix_spawnp
to return ENOENT, even though it successfully spawned the process in the given directory.posix_spawn_file_actions_addchdir_np
was introduced in macOS 10.15 first released in Oct 2019. I have tested macOS 10.15.7 and 11.0.1.Example offending program:
This prints:
I wanted to open this PR to get some feedback on possible solutions. Alternatives:
posix_spawn_file_actions_addchdir_np
only in that case.I looked at the XNU source code, but I didn't see anything obvious that would explain the behavior. The actual chdir succeeds, it is something else further down that fails, but I couldn't see where.
EDIT: I forgot to mention, relative exe paths with
current_dir
in general are discouraged (see #37868). I don't know if #37868 is fixable, since normalizing it would change the semantics for some platforms. Another option is to convert the executable to an absolute path with something like joining the cwd with the new cwd and the executable, but I'm uncertain about that.