Skip to content

Some diagnostics from do_spawn_posix are very terse #224

Description

@blackgnezdo

As of #208 on OpenBSD runInteractiveProcess uses do_spawn_posix. This means this kind of errors (demonstrated by process010 test):

λ> import System.Process
λ> rawSystem "/tmp/fdjskl" []
ExitFailure 127

The previous errors were more helpful as they included the filename that failed to be exec'd because there was an error reporting child_failed backdoor in fork_exec.c.

Activity

  1. blackgnezdo commented on Jan 5, 2022

    @blackgnezdo
    ContributorAuthor

    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)
    
  2. blackgnezdo commented on Jan 5, 2022

    @blackgnezdo
    ContributorAuthor
  3. bgamari commented on Jan 10, 2022

    @bgamari
    Contributor

    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.

  4. self-assigned this
    on Jan 11, 2022
  5. blackgnezdo commented on Jan 11, 2022

    @blackgnezdo
    ContributorAuthor

    Here you go. This is ktrace -i on rawSystem "/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.

  6. bgamari commented on Jan 11, 2022

    @bgamari
    Contributor

    I have managed to reproduce this in my OpenBSD VM. It appears that we are using posix_spawnp to spawn the process. Moreover, posix_spawnp claims 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 to exec when 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:

    1. 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 we exec'd it, but this seems quite improbable).
    2. Don't use posix_spawn at all on OpenBSD

    Now that I think of it, the race in (1) is actually already present in the current fork/exec runProcess implementation. I suppose could mitigate it by using fexecve.

  7. blackgnezdo commented on Jan 12, 2022

    @blackgnezdo
    ContributorAuthor

    I'd revert back to the previous fork/exec recipe for OpenBSD.

  8. bgamari commented on Jan 24, 2022

    @bgamari
    Contributor

    @blackgnezdo thanks for the feedback. I think this is what I will do

  9. added 2 commits that reference this issue on Feb 8, 2022
    fce319b
    7710b9a
  10. blackgnezdo commented on Feb 9, 2022

    @blackgnezdo
    ContributorAuthor

    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)
    
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions