• a pipe exercise

    From Meredith Montgomery@21:1/5 to All on Wed Mar 2 14:44:11 2022
    I took Lew Pitcher's program and gave myself the exercise of just
    switching parent and child's role. Briefly, Lew Pitcher's program forks
    and the child writes data to the parent, which executes less to page the output. What you find below is my own writing of that program (with the
    roles switched) --- so all errors are mine, of course.

    I think this program is wrong because the parent doesn't wait for the
    child, so the child finishes ``quickly'' and must be left in a zombie
    state until less exits. When less exits, it does so without calling
    wait(), so the child ends up being wait()ed by the init program. Things
    might end up well, but it's a totally flawed design.

    That's my understanding. I appreciate if you correct any
    misunderstandings here. Thank you.

    (*) Full program

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/wait.h>

    int main(int argc, char *argv[])
    {
    int pfd[2]; int r;

    r = pipe(pfd); if (r < 0) { perror("pipe"); exit(1); }
    r = fork(); if (r < 0) { perror("fork"); exit(2); }

    if (r == 0) {
    close(pfd[0]);
    r = dup2(pfd[1], STDOUT_FILENO); if (r < 0) { perror("dup2 child"); exit(4); }
    close(pfd[1]);
    for (int c = 1; c <= 100; ++c)
    printf("Line %d\n", c);
    fclose(stdout);
    exit(0);
    }

    close(pfd[1]);
    r = dup2(pfd[0], STDIN_FILENO); if (r < 0) { perror("dup2 parent"); exit(3); }
    close(pfd[0]);
    execl("/usr/bin/less","less",NULL);
    fprintf(stderr, "%s: execl() failed - %s\n", argv[0], strerror(errno));

    // who's gonna wait() for the child?
    exit(0);
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Meredith Montgomery on Wed Mar 2 18:29:50 2022
    Meredith Montgomery <mmontgomery@levado.to> writes:
    I took Lew Pitcher's program and gave myself the exercise of just
    switching parent and child's role. Briefly, Lew Pitcher's program forks
    and the child writes data to the parent, which executes less to page the >output. What you find below is my own writing of that program (with the >roles switched) --- so all errors are mine, of course.


    Keep in mind that there is no guarantee as to whether the child
    process runs before the parent, or that the parent runs before the
    child, or that they don't run _at the same time_ (e.g. on a multicore processor). In this case, the child could have run to completion before
    the parent returns from the fork() system call.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Meredith Montgomery on Wed Mar 2 20:43:52 2022
    On Wed, 02 Mar 2022 14:44:11 -0300, Meredith Montgomery wrote:

    I took Lew Pitcher's program and gave myself the exercise of just
    switching parent and child's role. Briefly, Lew Pitcher's program forks
    and the child writes data to the parent, which executes less to page the output. What you find below is my own writing of that program (with the roles switched) --- so all errors are mine, of course.

    It looks like a reasonable test program to me. I walked through it and
    didn't see any obvious problems.

    I think this program is wrong because the parent doesn't wait for the
    child, so the child finishes ``quickly'' and must be left in a zombie
    state until less exits. When less exits, it does so without calling
    wait(), so the child ends up being wait()ed by the init program. Things might end up well, but it's a totally flawed design.

    Perhaps not a CYA thorough design, but I wouldn't say "totally flawed".
    It /would/ be better to have the parent wait() for the child process, but
    since it doesn't, that child process (if it hasn't terminated) becomes an orphan process, not a zombie. (It would only be a zombie during the lifetime
    of the parent process.)

    As you alluded to, init(8) is specifically tasked with cleaning up the
    status of orphaned child processes. So long as the parent process exits
    in a timely manner (and yours does, more or less) there's no need to worry.
    Or, to put it another way, so long as the zombie doesn't live /too/ long,
    and there aren't /too/ many zombies, the system will live on.

    Remember, zombie processes starve the system by holding on to a limited resource: their place in the system's process state table. The more zombies, the fewer live processes can run. But, zombie processes are tolerable, so
    long as they don't live long enough to impact performance. They may be undesirable, and (consequently) a sign of "bad design", but so long as they /do/ die in a reasonable time, you can get away with them.

    That's my understanding. I appreciate if you correct any
    misunderstandings here. Thank you.

    [snip code]

    --
    Lew Pitcher
    "In Skills, We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Scott Lurndal on Wed Mar 2 20:30:26 2022
    On Wed, 02 Mar 2022 18:29:50 +0000, Scott Lurndal wrote:

    Meredith Montgomery <mmontgomery@levado.to> writes:
    I took Lew Pitcher's program and gave myself the exercise of just
    switching parent and child's role. Briefly, Lew Pitcher's program forks >>and the child writes data to the parent, which executes less to page the >>output. What you find below is my own writing of that program (with the >>roles switched) --- so all errors are mine, of course.


    Keep in mind that there is no guarantee as to whether the child
    process runs before the parent, or that the parent runs before the
    child, or that they don't run _at the same time_ (e.g. on a multicore processor). In this case, the child could have run to completion before
    the parent returns from the fork() system call.

    If I understand correctly, /that/ situation should result in a pipe
    that contains all the data from the child process, and (other than the
    write fd in the parent process) no open write fds.

    So long as the parent process closes that lone pipe write fd (which
    it does, in Meredith's code) the reader should properly receive EOF
    once it has read the entire contents of the (buffered) pipe.

    --
    Lew Pitcher
    "In Skills, We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)