using pipes and signals. - Unix

This is a discussion on using pipes and signals. - Unix ; Hello, 1) In C, I have created a pipe, and by fork statement a child. The parent send messages to user via pipe. When parent send messages to user via pipe - they are synchronized, but how can I ensure ...

+ Reply to Thread
Results 1 to 8 of 8

Thread: using pipes and signals.

  1. using pipes and signals.

    Hello,
    1) In C, I have created a pipe, and by fork statement a child.
    The parent send messages to user via pipe.
    When parent send messages to user via pipe - they are synchronized,
    but how can I ensure the child ends.

    2) The parent does : "wait" at it's end,
    is that all what necessary, or should I need some use of sigsuspend command
    ?
    How can I use the sigsuspend command at that case ?

    Need sample code, please.

    Thanks



  2. Re: using pipes and signals.

    Mr. X. wrote:
    > 1) In C, I have created a pipe, and by fork statement a child.
    > The parent send messages to user via pipe.


    The parent process sends data to the child process via the pipe,
    not to the "user".

    > When parent send messages to user via pipe - they are synchronized,


    What do you mean by "they are synchronized"? And who's "they"? And
    is synchronization important in your case (and why)?

    > but how can I ensure the child ends.


    Sorry, now you lost me completely. The child ends when it calls
    exit() or _exit() or abort() or returns from main() or gets killed.
    You can ensure that the child ends by either make it call one of
    those functions or to return from main() or by sending it a signal
    that kills it.

    > 2) The parent does : "wait" at it's end,
    > is that all what necessary, or should I need some use of sigsuspend
    > command?


    If the parent process wants (or needs) to wait for the child to
    finish calling wait() (or, perhaps better, waitpid()) is a good
    idea. But calling wait() won't make the child end. And what exact-
    ly has sigsuspend() to do with that?

    > Need sample code, please.


    Sorry, but please tell what this is all about before you expect
    help or even sample code. Perhaps you should post some code your-
    self and explain what you expect it to do - what you write here
    unfortunately doesn't make too much sense at the moment.

    Regard, Jens
    --
    \ Jens Thoms Toerring ___ jt@toerring.de
    \__________________________ http://toerring.de

  3. Re: using pipes and signals.

    Mr. X. wrote:
    > 1) In C, I have created a pipe, and by fork statement a child.
    > The parent send messages to user via pipe.
    > When parent send messages to user via pipe - they are synchronized,
    > but how can I ensure the child ends.


    I'm going to read between the lines here and make a guess.

    You're creating the pipe before forking. Then you're writing a
    bunch of stuff into the pipe in the parent, and then closing the
    pipe in the parent when you're done writing. You're hoping the
    child will see EOF when on the pipe, but mysteriously it doesn't.
    Am I right?

    If that is what you are doing, then here's the problem: you've
    forgotten that when you fork(), the child will get a copy of the
    *writing* end of the pipe as well. The pipe will not close until
    all the processes close it, and the child is holding it open. You
    need to close the writing end of the pipe in the child just after
    you fork().

    > 2) The parent does : "wait" at it's end,
    > is that all what necessary


    If the child exits, then of course wait() will work. That's what
    wait() is for. :-)

    - Logan

  4. Re: using pipes and signals.

    Here is some of my code :
    -------------------------
    ....
    int fd[2];
    ....

    if (pipe(fd) < 0)
    {
    perror("pipe error\n");
    exit(1);
    }
    if ( (pid = fork()) < 0) {
    perror("fork error\n");
    exit(1);
    }


    if (pid > 0) { /* parent */
    // changing stdout to : pipe write fd[1] enterence
    close(fd[0]);
    close(1);
    dup(fd[1]);
    close(fd[1]);
    // do some writing ...
    close(1); // **** should this line be ?? ****
    // *** sould I do some sigsuspend ... sigprocmask ... ?? ****
    if ( (pid = wait(&status)) < 0)
    {
    perror("wait error");
    exit(1);
    }
    }
    else {
    // changing stdin to : pipe read[1] enterence
    close(fd[1]);
    close(0);
    dup(fd[0]);
    close(fd[0]);
    // ... do some reading to pipe
    }

    .....
    The parent' output is the child's input (parent output is : fd[1] -
    pipe/write,
    and the child input is fd[0] - pipe/read).
    Look at the line : close(1).
    If I didn't do that, the wait was forever, because I don't know when the
    child ends
    (I assumes that child ends only if there is no message on the pipe.
    How should I know in the parent if the parent finished sending its messages
    via the pipe,
    because even after wait there may be a single send to the pipe,
    so I did the close(1) ).

    B.T.W. should I need use of sigsuspend (in order to suspend the
    child-termination signals) ?
    If so, how can I do that ?

    Need sample code, please.

    Thanks



  5. Re: using pipes and signals.

    Mr. X. wrote:
    > Here is some of my code :
    > -------------------------
    > ...
    > int fd[2];
    > ...


    > if (pipe(fd) < 0) {
    > perror("pipe error\n");
    > exit(1);
    > }
    > if ( (pid = fork()) < 0) {
    > perror("fork error\n");
    > exit(1);
    > }


    > if (pid > 0) { /* parent */
    > // changing stdout to : pipe write fd[1] enterence
    > close(fd[0]);
    > close(1);
    > dup(fd[1]);
    > close(fd[1]);


    This is ok (but I would use the macro STDOUT_FILENO instead of 1).
    And you could use

    dup2( fd[ 1 ], STDOUT_FILENO )

    instead of

    > close(1);
    > dup(fd[1]);


    > // do some writing ...


    Now here's the question of how you do the writing. If you use printf()
    you probably have to fflush() stdout in order to flush the internal
    buffers of the the C standard output functions. They treat a pipe
    like a file and output is only send out when the buffer is full (or
    you call fflush()).

    > close(1); // **** should this line be ?? ****


    You must have this line only if the child exits if it finds that
    it's standard input has been closed.

    > // *** sould I do some sigsuspend ... sigprocmask ... ?? ****


    I don't see any reason why.

    > if ( (pid = wait(&status)) < 0)
    > {
    > perror("wait error");
    > exit(1);
    > }
    > }
    > else {
    > // changing stdin to : pipe read[1] enterence
    > close(fd[1]);
    > close(0);
    > dup(fd[0]);
    > close(fd[0]);


    This is also ok (but you may use STDIN_FILENO instead of 0).

    > // ... do some reading to pipe
    > }


    > ....
    > The parent' output is the child's input (parent output is : fd[1] -
    > pipe/write,
    > and the child input is fd[0] - pipe/read).
    > Look at the line : close(1).
    > If I didn't do that, the wait was forever, because I don't know when the
    > child ends
    > (I assumes that child ends only if there is no message on the pipe.


    That's a question of how you write your child. If it exits only if
    it's standard input has been closed then you definitely need to
    close the write end of the pipe. But if the child exits for some
    other reason, the close() call is not strictly necessary.

    > How should I know in the parent if the parent finished sending its messages
    > via the pipe,
    > because even after wait there may be a single send to the pipe,
    > so I did the close(1) ).


    > B.T.W. should I need use of sigsuspend (in order to suspend the
    > child-termination signals) ?


    No

    > Need sample code, please.


    #include
    #include
    #include
    #include
    #include

    int main( void )
    {
    pid_t pid;
    int fd[ 2 ];

    if ( pipe( fd ) < 0 ) {
    perror( "pipe error\n" );
    exit( 1 );
    }

    if ( ( pid = fork( ) ) < 0 ) {
    perror( "fork error\n" );
    exit( 1 );
    }

    if ( pid == 0 ) { /* child */
    char buf[ 100 ];

    close( fd[ 1 ] );
    dup2( fd[ 0 ], STDIN_FILENO );
    close( fd[ 0 ] );

    while ( fgets( buf, sizeof( buf ), stdin ) )
    printf( "Here's what I got: %s", buf );

    printf( "Nothing to read anymore, exiting\n" );
    _exit( 0 );
    }

    close( fd[ 0 ] );
    dup2( fd[ 1 ], STDOUT_FILENO );
    close( fd[ 1 ] );

    printf( "XXXXXXXX\n" );
    fflush( stdout ); /* Required if you use printf() */

    /* You need the close() call here since the child waits forever for
    input and only exits when it finds its standard input having been
    closed. But if the child would just read a single line and then
    exit the close() call would not be strictly necessary (but it
    wouldn't hurt, since it makes no sense to keep the file descriptor
    open any longer). But in that case you could also delay the close()
    to e.g. after the waitpid() call. */

    close( STDOUT_FILENO );

    if ( waitpid( pid, NULL, 0 ) < 0 ) {
    perror( "waitpid error" );
    exit( 1 );
    }

    return 0;
    }
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ jt@toerring.de
    \__________________________ http://toerring.de

  6. Re: using pipes and signals.

    Thanks ...

    For one thing you have said :
    >
    >> close(1); // **** should this line be ?? ****

    >
    > You must have this line only if the child exits if it finds that
    > it's standard input has been closed.
    >


    What I do is doing simulation of shell :
    i.e for the command :
    cat myfile | wc -l

    it should return the no. of lines of myfile.
    wc -l runs on the child process (then I do another fork ...)

    I think that the command that are executed on execvp command (on child),
    should wait internal for an end-of-file signal,
    because for that if I didn't do the : close(1),
    the wait command, as I have mentioned will wait forever
    (that's the case anyway)

    What may be the cause of the above waiting (forever) ?

    If necessary, need some other code, which resolve the above problem, please.

    Thanks



  7. Re: using pipes and signals.

    Mr. X. wrote:
    > For one thing you have said :
    > >
    > >> close(1); // **** should this line be ?? ****

    > >
    > > You must have this line only if the child exits if it finds that
    > > it's standard input has been closed.
    > >


    > What I do is doing simulation of shell :
    > i.e for the command :
    > cat myfile | wc -l


    > it should return the no. of lines of myfile.
    > wc -l runs on the child process (then I do another fork ...)


    > I think that the command that are executed on execvp command (on child),
    > should wait internal for an end-of-file signal,
    > because for that if I didn't do the : close(1),
    > the wait command, as I have mentioned will wait forever
    > (that's the case anyway)


    There's nothing like an "end-of-file signal". Many programs (like
    e.g. 'wc') wait for new input until the file descriptor they read
    on get gets closed, which is the pipes equivalent for reaching the
    end of a file, and this you can achieve by closing the write end
    of the pipe. You should definitely do that when you implement such
    a shell style piping functionality because otherwise such programs
    simply won't stop (unless you kill them explicitely) and thus you
    would wait() indefintely.

    You only can leave out closing the write end of the pipe in
    the parent if you know for sure that you're dealing with a
    program on the other end that will exit even though the
    write end of the pipe hasn't been closed (perhaps because
    you send it some data that tell it to stop). But that's
    not something you can assume when you write a shell-like
    program. So definitely keep the close() call.

    > What may be the cause of the above waiting (forever) ?


    You are waiting for the child process to die. But the child
    process doesn't exit but instead waits for more input. So
    you must tell the child that no more input will be coming by
    closing the write end of the pipe. A (correctly written)
    program that keeps waiting for more input will get an indi-
    cation that it's input has been closed (e.g. a NULL return
    value from fgets() or 0 from a call of read() etc.) and exit.

    > If necessary, need some other code, which resolve the above
    > problem, please.


    What problem do you mean?
    Regards, Jens
    --
    \ Jens Thoms Toerring ___ jt@toerring.de
    \__________________________ http://toerring.de

  8. Re: using pipes and signals.

    >> If necessary, need some other code, which resolve the above
    >> problem, please.

    >
    > What problem do you mean?
    > Regards, Jens


    It seems that the close(1) is enough, as my prior example,
    (I just want to understand why my code works).
    No other code is needed.

    Thanks



+ Reply to Thread