Skip to content

processT251 failure (fd 0 considered special?) #266

@blackgnezdo

Description

@blackgnezdo

When running on OpenBSD 7.2 as a part of my attempt to test ghc HEAD I ran into a failure which is easier to observe standalone:

% ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.2.4
% ghc ~/s/ghc/libraries/process/tests/processT251.hs -o /tmp/z
ghc ~/s/ghc/libraries/process/tests/processT251.hs -o /tmp/z
[1 of 1] Compiling Main             ( /home/greg/s/ghc/libraries/process/tests/processT251.hs, /home/greg/s/ghc/libraries/process/tests/processT251.o )
Linking /tmp/z ...
% /tmp/z
parent start
child start
processT251: ./processT251: createProcess: close: invalid argument (Bad file descriptor)
z: user error (Pattern match failure in 'do' block at /home/greg/s/ghc/libraries/process/tests/processT251.hs:20:5-15)
% 

Tracing the syscalls is a bit tedious but boils down to these salient parts:

 46520 processT251 GIO   fd 1 wrote 13 bytes
       "parent start
       "
 46520 processT251 CALL  pipe(0x7f7ffffca5e8)
 46520 processT251 STRU  int [2] { 3, 4 }
 46520 processT251 RET   pipe 0
 46520 processT251 CALL  vfork()
 89659 processT251 RET   vfork 0
 89659 processT251 CALL  execve(0x224e040f0,0x224e04158,0x7f7ffffce9a8)
 89659 processT251 NAMI  "./processT251"
 89659 processT251 ARGS  
	[0] = "./processT251"
	[1] = "child"
 46520 processT251 RET   vfork 89659/0x15e3b
...
 89659 processT251 GIO   fd 1 wrote 12 bytes
       "child start
       "
 89659 processT251 RET   write 12/0xc
 89659 processT251 CALL  pipe(0x7f7ffffec6f8)
 89659 processT251 STRU  int [2] { 0, 3 }      ---------------------------------- [1]
 89659 processT251 RET   pipe 0
 89659 processT251 CALL  vfork()

 23176 processT251 RET   vfork 0
 23176 processT251 CALL  close(0)               ----------------------------------[2]
 23176 processT251 RET   close 0
 23176 processT251 CALL  fcntl(3,F_SETFD,FD_CLOEXEC)
 23176 processT251 RET   fcntl 0
...
 23176 processT251 CALL  close(0)              -----------------------------------[3]
 23176 processT251 RET   close -1 errno 9 Bad file descriptor
 23176 processT251 CALL  write(3,0x7f7ffffec628,0x8)
 23176 processT251 GIO   fd 3 wrote 8 bytes
       "\M-h\M^Z \0\0\0\0\0"
 23176 processT251 RET   write 8
 23176 processT251 CALL  write(3,0x7f7ffffec634,0x4)
 23176 processT251 GIO   fd 3 wrote 4 bytes
       "	\0\0\0"

So the "child" is PID 89659.
[1] "child" gets a pipe with a pair of descriptors [0, 3]
[2] "child2" closes fd0 successfully once
[3] "child2" fails to close fd0 the second time (it's no longer open)

Maybe there's an expectation somewhere that pipe won't allocate these FDs because they are reserved? I don't think they are per any standard and since "child" already wanted to run with std_in = NoStream, its wish is fulfilled and fd=0 is used otherwise.

Metadata

Metadata

Assignees

No one assigned

    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