LinuxQuestions.org
Latest LQ Deal: Linux Power User Bundle
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-31-2013, 11:05 PM   #1
Kurt M. Weber
Member
 
Registered: Oct 2003
Distribution: Slackware
Posts: 335

Rep: Reputation: 35
Closing write end of a pipe does not seem to cause EOF to appear on read end...


I've got a program I wrote to test something for a project I'm about to work on.

What I'm trying to do in this test program is write the same data to the stdin of two separate child processes via a pipe (one for each), each of which read it, display it, and then exit.

Whenever I close all references to the write end of a given pipe, the next time the child calls read() it should return 0. Unfortunately, that does not seem to happen. Instead, the children simply hang, and I can't for the life of me figure out why.

Code follows:
Code:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]){
        pid_t pid_cmd1, pid_cmd2;
        int cmd1_pipes[2], cmd2_pipes[2];
        char testbuf[100];
        int numbytes;

        pipe(cmd1_pipes);
        pipe(cmd2_pipes);
        pid_cmd1 = fork();

        memset((void *)testbuf, '\0', (size_t)100);

        if (pid_cmd1 == (pid_t)0){
                close(0);
                dup(cmd1_pipes[0]);
                close(cmd1_pipes[0]);
                close(cmd1_pipes[1]);

                sleep(5);
                while(read(0, (void *)testbuf, (size_t)100)){
                        write(1, (void *)testbuf, (size_t)100);
                        memset((void *)testbuf, '\0', (size_t)100);
                }

                exit(EXIT_SUCCESS);
        }

        pid_cmd2 = fork();

        if (pid_cmd2 == (pid_t)0){
                close(0);
                dup(cmd2_pipes[0]);
                close(cmd2_pipes[0]);
                close(cmd2_pipes[1]);

                sleep(10);
                while(read(0, (void *)testbuf, (size_t)100)){
                        write(1, (void *)testbuf, (size_t)100);
                        memset((void *)testbuf, '\0', (size_t)100);
                }

                exit(EXIT_SUCCESS);
        }

        close(cmd1_pipes[0]);
        close(cmd2_pipes[0]);

        while (read(0, (void *)testbuf, 100)){
                write(cmd1_pipes[1], (void *)testbuf, (size_t)100);
                write(cmd2_pipes[1], (void *)testbuf, (size_t)100);
                memset((void *)testbuf, '\0', (size_t)100);
        }

        write(1, "Gotten this far\n", 16);

        if(close(cmd1_pipes[1])){
                write(1, "Error closing pipe 1\n", 21);
        }

        if (close(cmd2_pipes[1])){
                write(1, "Error closing pipe 2\n", 21);
        }

        write(1, "And now this far\n", 17);

        waitpid(pid_cmd1, NULL, 0);
        waitpid(pid_cmd2, NULL, 0);

        return EXIT_SUCCESS;
}
It compiles without errors; I run it by piping a short text file (the first few lines of Bob Dylan's Visions of Johanna, if you're wondering) into it, which is where it obtains the data it sends to its children.

Both children display the text correctly, at the proper time intervals.

The parent process gets to the "And now this far" write, but the first waitpid() never returns since the first child process never exits (for that matter, nor does the second one).

I can't figure out what I'm missing here. Any suggestions?
 
Old 04-01-2013, 12:12 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 3,433

Rep: Reputation: 1054Reputation: 1054Reputation: 1054Reputation: 1054Reputation: 1054Reputation: 1054Reputation: 1054Reputation: 1054
Check whether 'read' returns negative value (if so, print errno)
 
Old 04-01-2013, 12:28 AM   #3
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,317

Rep: Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485Reputation: 1485
Code:
    pipe(cmd1_pipes);
    pipe(cmd2_pipes);
    pid_cmd1 = fork();
...
    if (pid_cmd1 == (pid_t)0){
        ...
        close(cmd1_pipes[0]);
        close(cmd1_pipes[1]);
        ...
        exit(EXIT_SUCCESS);
    }

    pid_cmd2 = fork();

    if (pid_cmd2 == (pid_t)0){
        ...
        close(cmd2_pipes[0]);
        close(cmd2_pipes[1]);
        ...
        exit(EXIT_SUCCESS);
    }
...
    close(cmd1_pipes[0]);
    close(cmd2_pipes[0]);
Currently both child processes are seeing all the pipes, either close cmd1_pipes before before the second fork, and create cmd2_pipes after the first fork, or else close cmd1_pipes in the second child and cmd2_pipes in the first child.

Also, would recommend:
Code:
    memset(testbuf, '\0', sizeof testbuf);
    // instead of
    memset((void *)testbuf, '\0', (size_t)100);

    // and
    dup2(cmd1_pipes[0], STDIN_FILENO);
    // instead of
    close(0);
    dup(cmd1_pipes[0]);
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Errors while using awk script for calculating average end to end delay in ns2 NS2User2012 Linux - Networking 4 02-17-2013 11:20 AM
[SOLVED] EOF at end of command? sgull Linux - Newbie 2 03-29-2012 06:04 PM
gui read out of back end command lines from gui front end activation? how? Siljrath Linux - General 0 10-24-2008 10:11 AM
Identifying process at the other end of named pipe natris Programming 2 07-25-2008 08:05 AM
End Of File Key (EOF) in linux ereeno Linux - Software 3 08-05-2003 03:05 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:06 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration