pread()/pwrite() fail with EBADF in child process if already used before fork()

Christian Franke Christian.Franke@t-online.de
Tue Sep 24 10:15:37 GMT 2024


Christian Franke via Cygwin wrote:
> 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.

Possible fix: 
https://sourceware.org/pipermail/cygwin-patches/2024q3/012793.html

-- 
Regards,
Christian



More information about the Cygwin mailing list