This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug stdio/23151] New: A forked process with unclosed file does lseek before exit and can cause infinite loop in parent I/O


https://sourceware.org/bugzilla/show_bug.cgi?id=23151

            Bug ID: 23151
           Summary: A forked process with unclosed file does lseek before
                    exit and can cause infinite loop in parent I/O
           Product: glibc
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: stdio
          Assignee: unassigned at sourceware dot org
          Reporter: jonathan.leffler at gmail dot com
  Target Milestone: ---

See Stack Overflow Q&A:
*
https://stackoverflow.com/questions/50110992/why-does-forking-my-process-cause-the-file-to-be-read-infinitely
*
https://stackoverflow.com/questions/50244579/unwanted-child-processes-being-created-while-file-reading

As the accepted answer to the "why does forking my process" question shows,
when the child process exits, it seeks on the file descriptor towards the
beginning of the file, thus changing the position of the read position in the
(shared) open file description, potentially leading to an infinite loop in the
parent process as it never encounters EOF.

The output from strace (strace -ff -o st-out -- neof97) for the children shows:

$ cat st-out.80833
lseek(0, -63, SEEK_CUR)                 = 21
exit_group(0)                           = ?
+++ exited with 0 +++
$ cat st-out.80834
lseek(0, -42, SEEK_CUR)                 = -1 EINVAL (Invalid argument)
exit_group(0)                           = ?
+++ exited with 0 +++
$ cat st-out.80835
lseek(0, -21, SEEK_CUR)                 = 0
exit_group(0)                           = ?
+++ exited with 0 +++
$ cat st-out.80836
exit_group(0)                           = ?
+++ exited with 0 +++
$


One version of the code that shows the problem is (neof97.c).  It limits the
'infinite input' to 30 lines.

#include "posixver.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

enum { MAX = 100 };

int main(void)
{
    if (freopen("input.txt", "r", stdin) == 0)
        return 1;
    char s[MAX];
    for (int i = 0; i < 30 && fgets(s, MAX, stdin) != NULL; i++)
    {
        // Commenting out this region fixes the issue
        int status;
        pid_t pid = fork();
        if (pid == 0)
        {
            exit(0);
        }
        else
        {
            waitpid(pid, &status, 0);
        }
        // End region
        printf("%s", s);
    }
    return 0;
}

The file input.txt can be any text; 4 lines of 20 random characters each is
sufficient to show the bug.

If the file is explicitly closed in the child, the lseek() does not occur which
avoids the problem.

The problem was reproduced in a Ubuntu 16.04 LTS system running as a VM under
VMWare Fusion on a MacBook Pro running macOS 10.13.4 (High Sierra).  When the
same code was recompiled and run on the macOS host operating system, the
problem was not exhibited.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]