JonathanPark
JonathanPark

Reputation: 35

C/UNIX Interprocess communication sending a string with pipe

I am writing a code in which children and parent should give time information to one other and the receiver should print it.When I find time on parent process and try to print it on parent process It works fine.But when I try to send it through a pipe it writes a line with weird question marks and a z letter.I commented the last line in case if someone tries to execute the code. SOrry for the messy code but I cannot fix it in my current keyboard.

  #include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include<signal.h>
#include<stdint.h>
#include<string.h>
#include<time.h>


void formatted_time(char* sender_name, char* receiver_name, char output[]);
void formatted_time(  char* sender_name ,  char* receiver_name, char output[])
{
  struct timeval tv;
  time_t nowtime;
  struct tm *nowtm;
char tmbuf[80];
  gettimeofday(&tv, NULL);
  nowtime = tv.tv_sec;
  nowtm = localtime(&nowtime);
  strftime(tmbuf,80 , "%Y-%m-%d %H:%M:%S",
            nowtm);
  sprintf(output, "%s: Time at %s is %s.", receiver_name, sender_name,  tmbuf);
}

int main(int argc, char** argv)
{
     char* parent="Parent";
     char* child1="Child1";
     char* child2="Child2";
    char result[80];
    char buffer[80];
    int firstchild,secondchild,read1,read2,read3;
    firstchild=fork();
        int mypipe[2];
    int mypipe2[2];
    int mypipe3[2];

        if(pipe(mypipe) == -1) {
          perror("Pipe failed");
          exit(1);
        }

        if(firstchild == 0)            //first child
        {
         close(mypipe[1]);    //Closing  the output  of pipe
    sleep(3);
    read1=read(mypipe[0],buffer,sizeof(buffer));    
     printf("%s\n",buffer);



        }else{
    secondchild=fork();        //Creating second child

        if(secondchild == 0)            //2nd child
        {

        sleep(6);


        }else{            //Parent
    close(mypipe[0]);     //Closing the input of pipe
    formatted_time(parent,child1,result);   
    write(mypipe[1],result,strlen(result)+1);
    //printf("%s\n",result);

Upvotes: 1

Views: 161

Answers (2)

Martin Zabel
Martin Zabel

Reputation: 3659

You are forking the first child before you are creating the pipe. Thus, you create two distinct pipes: one in the parent and one in the child. Afterwards, if you read from the pipe created in the first child, the read returns 0, indicating that no data has been read. Thus, data in the buffer is invalid and the printf is prohibited. Always check the return code of API calls!

The user "nsilent22" already provided a good clean-up of your code. After adding 3 closing brackets } at the end to close all blocks, you have at least move the fork after creating the pipe:

firstchild=fork();
if (firstchild == 0) { // first child

And at the read call, you should check the return code:

  read1=read(mypipe[0],buffer,sizeof(buffer));
  if (read1 <= 0) {
    printf("read failed with code %d\n, ", read1);
  } else {
    printf("%s\n",buffer);
  }

Upvotes: 1

nsilent22
nsilent22

Reputation: 2863

Your problem is you do a fork call before you create your pipe. So in fact you read reads nothing, and your printf prints garbage that was on the stack where buffer was allocated.

Here is your code fixed. I also added a wait call in the parent to avoid child printing to the console out of nowhere :)

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

void formatted_time(char *sender_name,char *receiver_name, char output[]) {
    struct timeval tv;
    time_t nowtime;
    struct tm *nowtm;
    char tmbuf[80];
    gettimeofday(&tv, NULL);
    nowtime = tv.tv_sec;
    nowtm = localtime(&nowtime);
    strftime(tmbuf,80, "%Y-%m-%d %H:%M:%S", nowtm);
    sprintf(output, "%s: Time at %s is %s.", receiver_name, sender_name, tmbuf);
}

int main(int argc, char** argv) {
    char* parent="Parent";
    char* child1="Child1";
    char result[80];
    char buffer[80];
    int firstchild, secondchild, read1;

    int mypipe[2];

    if (pipe(mypipe) == -1) {
        perror("Pipe failed");
        exit(1);
    }

    firstchild=fork();
    if (firstchild == 0) { // first child
        close(mypipe[1]); //Closing  the output  of pipe
        sleep(3);
        read1 = read(mypipe[0], buffer, sizeof(buffer));    
        printf("%d %s\n", read1, buffer);
    } else {
        secondchild=fork(); //Creating second child
        if(secondchild == 0) { //2nd child
            sleep(6);
        } else { //Parent
            close(mypipe[0]); //Closing the input of pipe
            formatted_time(parent, child1, result); 
            int w;
            w = write(mypipe[1], result, strlen(result)+1);
            printf("%d bytes written\n", w);
            wait(NULL);
        }
    }
    return 0;
}

Upvotes: 2

Related Questions