pread()/pwrite() fail with EBADF in child process if already used before fork()
Christian Franke
Christian.Franke@t-online.de
Mon Sep 23 12:52:52 GMT 2024
Christian Franke via Cygwin wrote:
> Found during test of 'stress-ng --pseek ...' from current upstream
> stress-ng git HEAD:
>
> Testcase:
>
> $ uname -r
> 3.5.4-1.x86_64
>
> $ cat pfail.c
> #include <fcntl.h>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/wait.h>
>
> int main()
> {
> int fd = open("pwrite.tmp", O_RDWR|O_CREAT|O_BINARY, 0666);
> if (fd < 0) {
> perror("open"); return 1;
> }
>
> char c = 42;
> if (pwrite(fd, &c, 1, 0) < 0)
> perror("pwrite");
>
> if (fork() == 0) {
> if (pread(fd, &c, 1, 0) < 0)
> perror("pread");
> _exit(0);
> }
>
> int status;
> wait(&status);
> return 0;
> }
>
> $ make pfail
> cc pfail.c -o pfail
>
> $ ./pfail
> pread: Bad file descriptor
>
> $ strace ./pfail
> ...
> 617 75356 [main] pfail 10826 dofork: 10827 = fork()
> 82 11289 [main] pfail 10827 seterrno_from_nt_status:
> /usr/src/debug/cygwin-3.5.4-1/winsup/cygwin/fhandler/disk_file.cc:1883
> status 0xC0000008 -> windows error 6
> 80 75436 [main] pfail 10826 wait4: calling proc_subproc, pid -1,
> options 0
> 76 11365 [main] pfail 10827 geterrno_from_win_error: windows
> error 6 == errno 9
> 78 75514 [main] pfail 10826 proc_subproc: args: 5, -7728
> 64 11429 [main] pfail 10827 pread: -1 = pread(3, 0x7FFFFCC0B, 1,
> 0), errno 9
> ...
>
>
> The problem does not occur if there is no pread()/pwrite() before the
> fork(). This suggests that the child process inherits the extra handle
> value used to keep the original seek position, but not the actual handle.
>
The mentioned extra handle 'prw_handle' is set to null after fork here:
https://cygwin.com/git/?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/fhandler/disk_file.cc;h=f4c21d3#l1698
But a test suggests that fhandler_disk_file::fixup_after_fork() is never
called or debug_printf() does not work if called in this function.
Thoughts?
More information about the Cygwin
mailing list