cprocesspipeforkpipelining

Why will not my code, which implements pipelining in C programming, out a concatenated string as intended?


I am following the example code I have found on a website which demonstrates how pipelining in C programming works. Specifically with the use of pipe() and fork(). The provided program is made to concatenate an input string with a fixed string put into the program. There seems to be no errors in the code. However, every time I run it, there is no output string at all. Right now, the main libraries are removed just to make the code more clear.

//Two pipes used
//One pipe goes from parent process (process 1) to the child process (process 2)

//Remember, '0' in the array means 'read end'
//'1' in the array means write end

int p12[2];
int p21[2];

//Now declare the strings
char fixed_str[] = "at tutorialspoint";
char input_str[100];

//Making the first parent process 
pid_t P; 

//Making sure the pipes are properly made and declared
if (pipe(p12)==-1 || pipe(p21)==-1)
{
    //fprintf simply sends formatted output to a stream
    //'stderr' is the standard error message
    //essentially, print below if there is an error 
    
    fprintf(stderr, "fork Failed");
    return 1;
}

//Now to take in the input string from user
scanf("%99s", input_str);

//Now to make the second/child process 
P = fork();

//If <0, the process creation failed
if ( P < 0 )
{
    fprintf(stderr, "fork Failed");
    return 1;
}
//If P > 0, which will be the process ID of the child 
//process to the parent process
//Essentially, this is the parent process which will
//be executed
else if ( P > 0 )
{
    //Declare the concatenated string
    char concat_str[100];
    
    //Close the 'read end' for pipe going from pipe 1 to pipe 2
    //It is not needed write now.
    close(p12[0]);
    
    //Write to the 'write end' for pipe going from pipe 1 to pipe 2 
    write(p12[1], input_str, strlen(input_str)+1);
    
    //Now close the write end 
    close(p12[1]);
    
    //Now, focus on the pipe from process 2 (child) back to process 1 (parent)
    //First, have the program wait so everything else can happen 
    wait(NULL);
    
    //Next, close the write end of the pipe from process 2 to 1 
    //It is not needed 
    close(p21[0]);
    
    //Now, read the concatenated string from the child process (2)
    //The child process would have sent it through the pipe from process 2 to process 1 
    //Therefore, get it from there 
    read(p21[0], concat_str, 100);
    printf("Concatenated string: %s", concat_str);
    
    //Then close the read end of this pipe. It is not needed anymore
    close(p21[0]);
    
    //Exit the parent process 
    exit(0);
}

//Now, process 2, the child process. 
//Remember this is shown by = 0
else
{
    //Close the write end of the pipe from process 1 to 2. You dont need it 
    //Redeclare the concatenated string 
    char concat_str[100] = ".";
    
    //Now, to take the string sent from process 1 (parent),
    //which is currently sitting in pipe 1 to 2. 
    //The process will read it and call it 'concat_str'
    read(p12[0], concat_str, 100);
    
    //This is where the addition of the new string begins
    //See how many characters are in the inputted string 
    int k = strlen(concat_str);
    
    //Declare an integer for the new fixed string 
    //Reminder: char fixed_str[] = " at tutorialspoint";
    int i; 
    
    //Now to do it
    for (i = 0; i < strlen(fixed_str); i++)
    {
        concat_str[k++] = fixed_str[i];
        concat_str[k] = '\0';
    }
    //concat_str[k] = '\0';
    
    //Close the read ends of the pipes. They are not needed 
    close(p12[0]);
    close(p21[0]);
    
    //Now finally, write this new string back to process 1 (parent process)
    write(p21[1], concat_str, strlen(concat_str)+1);
    
    //Now, close this pipe and exit 
    close(p21[1]);
    exit(0);
}
return 0;

Solution

  • The line close(p21[0]); is closing the read end of the pipe going from process 2 to process 1. This will result in a broken pipe error when the parent process tries to read from the pipe later. You want to close the write end instead so this:

    //Now, focus on the pipe from process 2 (child) back to process 1 (parent)
    //First, have the program wait so everything else can happen 
    wait(NULL);
        
    //Next, close the write end of the pipe from process 2 to 1 
    //It is not needed 
    close(p21[0]);
    

    Should be changed to this:

    //Now, focus on the pipe from process 2 (child) back to process 1 (parent)
    //First, have the program wait so everything else can happen 
    wait(NULL);
        
    //Next, close the write end of the pipe from process 2 to 1 
    //It is not needed 
    close(p21[1]);