Repository navigation
Some diagnostics from do_spawn_posix are very terse #224
Description
Activity
FWIW, the previous error (achieved by breaking the configure test) is:
λ> rawSystem "/tmp/fdjskl" [] *** Exception: /tmp/fdjskl: rawSystem: exec: does not exist (No such file or directory)@bgamari FYI
Thanks @blackgnezdo!
I'll admit that I'm quite perplexed by this failure as I cannot reproduce it under Linux. For instance,
λ> import System.Process λ> rawSystem "/asdf" *** Exception: /asdf: rawSystem: posix_spawnp: does not exist (No such file or directory)It seems to me that this must be OS dependent. It would be helpful to have
strace(or equivalent) output from the test program.Here you go. This is
ktrace -ionrawSystem "/tmp/fdjskl" [] >>= print:13579 a CALL fork() 13579 a RET fork 88705/0x15a81 88705 a RET fork 0 13579 a CALL kbind(0x7f7ffffcb078,24,0x161951d7b444b3c) 13579 a RET kbind 0 88705 a CALL sigaction(SIGINT,0x7f7ffffcb0c0,0) 13579 a CALL kbind(0x7f7ffffcb078,24,0x161951d7b444b3c) 88705 a STRU struct sigaction { handler=SIG_DFL, mask=0<>, flags=0<> } 88705 a RET sigaction 0 13579 a RET kbind 0 88705 a CALL sigaction(SIGQUIT,0x7f7ffffcb0c0,0) 88705 a STRU struct sigaction { handler=SIG_DFL, mask=0<>, flags=0<> } 88705 a RET sigaction 0 88705 a CALL execve(0x8cdb61060b0,0x8cdb61060e0,0x7f7ffffcf528) 88705 a NAMI "/tmp/fdjskl" 88705 a RET execve -1 errno 2 No such file or directory 13579 a CALL kbind(0x7f7ffffcb198,24,0x161951d7b444b3c) 13579 a RET kbind 0 88705 a CALL exit(127) 13579 a CALL wait4(88705,0x7f7ffffcb26c,0<>,0) 13579 a RET wait4 88705/0x15a81 13579 a CALL sigprocmask(SIG_BLOCK,0x2<SIGINT>) 13579 a RET sigprocmask 0<> 13579 a CALL sigaction(SIGINT,0x7f7ffffcb238,0) 13579 a STRU struct sigaction { sigaction=0x8cae27a9650, mask=0<>, flags=0x40<SA_SIGINFO> } 13579 a RET sigaction 0 13579 a CALL sigprocmask(SIG_SETMASK,0<>) 13579 a RET sigprocmask 0x2<SIGINT> 13579 a CALL sigprocmask(SIG_BLOCK,0x4<SIGQUIT>) 13579 a RET sigprocmask 0<> 13579 a CALL sigaction(SIGQUIT,0x7f7ffffcb238,0) 13579 a STRU struct sigaction { handler=SIG_DFL, mask=0<>, flags=0<> } 13579 a RET sigaction 0 13579 a CALL sigprocmask(SIG_SETMASK,0<>) 13579 a RET sigprocmask 0x4<SIGQUIT> 13579 a CALL kbind(0x7f7ffffcb1c8,24,0x161951d7b444b3c) 13579 a RET kbind 0 13579 a CALL fcntl(1,F_ISATTY) 13579 a RET fcntl 1 13579 a CALL kbind(0x7f7ffffcb168,24,0x161951d7b444b3c) 13579 a RET kbind 0 13579 a CALL poll(0x7f7ffffcb240,1,0) 13579 a STRU struct pollfd { fd=1, events=0x4<POLLOUT>, revents=0x4<POLLOUT> } 13579 a RET poll 1 13579 a CALL kbind(0x7f7ffffcb1c8,24,0x161951d7b444b3c) 13579 a RET kbind 0 13579 a CALL write(1,0x8cdb61f2010,0x10) 13579 a GIO fd 1 wrote 16 bytes "ExitFailure 127 "Note, this is the behavior with both 8.10.6 (available in OpenBSD packages) and ghc HEAD.
I have managed to reproduce this in my OpenBSD VM. It appears that we are using
posix_spawnpto spawn the process. Moreover,posix_spawnpclaims to return successfully, returning a valid pid in the process, despite the path not existing. However, it's only when the spawned process finally gets toexecwhen it realizes that the executable image doesn't exist, at which point it returns with exit code 127. It appears that this may be alluded to in the OpenBSD man page.Unfortunately, it appears that this is permitted under the SUSv3:
... if the error occurs after the calling process successfully returns, the child process exits with exit status 127.
This is quite annoying as it makes it exceedingly difficult to offer sensible error messages in general.
I'm honestly not sure what to do about this. I see a few options:
- Mitigate the problem by checking for the existence of the image before calling
posix_spawn, allowing us to catch this case most of the time (there would still be a potential race window where the image was deleted before weexec'd it, but this seems quite improbable). - Don't use
posix_spawnat all on OpenBSD
Now that I think of it, the race in (1) is actually already present in the current fork/exec
runProcessimplementation. I suppose could mitigate it by usingfexecve.- Mitigate the problem by checking for the existence of the image before calling
I'd revert back to the previous fork/exec recipe for OpenBSD.
@blackgnezdo thanks for the feedback. I think this is what I will do
- added 2 commits that reference this issue
on Feb 8, 2022 I verified that #232 makes the diagnostics better:
$ ./inplace/bin/ghc-stage2 --interactive GHCi, version 9.3.20220209: https://www.haskell.org/ghc/ :? for help ... λ> import System.Process λ> rawSystem "/tmp/fdjskl" [] *** Exception: /tmp/fdjskl: rawSystem: exec: does not exist (No such file or directory)
As of #208 on OpenBSD
runInteractiveProcessusesdo_spawn_posix. This means this kind of errors (demonstrated byprocess010test):The previous errors were more helpful as they included the filename that failed to be exec'd because there was an error reporting
child_failedbackdoor infork_exec.c.