[Bug manual/25555] New: Not closing read-en of pipe avoid kernel sending SIGPIPE to previous process in pipeline

abarthel at student dot 42.fr sourceware-bugzilla@sourceware.org
Fri Feb 14 12:10:00 GMT 2020


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

            Bug ID: 25555
           Summary: Not closing read-en of pipe avoid kernel sending
                    SIGPIPE to previous process in pipeline
           Product: glibc
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: manual
          Assignee: unassigned at sourceware dot org
          Reporter: abarthel at student dot 42.fr
                CC: mtk.manpages at gmail dot com
  Target Milestone: ---

Overview: In section 28.5.3 Launching Jobs of Libc Manual, nor launch_job nor
launch_process function close read-end of pipe process which leads the kernel
not to send SIGPIPE to the previous process in the pipeline.

Steps to Reproduce: Executing launch_job and launch_process together in a
program that runs a pipeline such as "ls -lR / | hostname".

Actual Results: When doing so, "ls -lR /" does not receive SIGPIPE from the
kernel when "hostname" ends but instead it is suspended. In this situation we
need to kill manually "ls -lR /" which is suspended.

Expected Results: When running "ls -lR / | hostname", as soon as hostname ends,
"ls -lR /" should receive SIGPIPE and exit.

Additional Information: I suggest to add a single line to launch_job to ensure
read-end of pipe will actually be closed, avoiding leaving a pipe in a single
process ("ls" in the example).

void
launch_job (job *j, int foreground)
{
  process *p;
  pid_t pid;
  int mypipe[2], infile, outfile;

  infile = j->stdin;
  for (p = j->first_process; p; p = p->next)
    {
      /* Set up pipes, if necessary.  */
      if (p->next)
        {
          if (pipe (mypipe) < 0)
            {
              perror ("pipe");
              exit (1);
            }
          outfile = mypipe[1];
        }
      else
        outfile = j->stdout;

      /* Fork the child processes.  */
      pid = fork ();
      if (pid == 0)
        {
        /* This is the child process.  */
           if (infile != mypipe[0]) /* Close read-end of pipe */
                close(mypipe[0]);
           launch_process (p, j->pgid, infile,
                        outfile, j->stderr, foreground);
        }
      else if (pid < 0)
        {
          /* The fork failed.  */
          perror ("fork");
          exit (1);
        }
      else
        {
          /* This is the parent process.  */
          p->pid = pid;
          if (shell_is_interactive)
            {
              if (!j->pgid)
                j->pgid = pid;
              setpgid (pid, j->pgid);
            }
        }

      /* Clean up after pipes.  */
      if (infile != j->stdin)
        close (infile);
      if (outfile != j->stdout)
        close (outfile);
      infile = mypipe[0];
    }

  format_job_info (j, "launched");

  if (!shell_is_interactive)
    wait_for_job (j);
  else if (foreground)
    put_job_in_foreground (j, 0);
  else
    put_job_in_background (j, 0);
}

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


More information about the Glibc-bugs mailing list