w2lame
w2lame

Reputation: 2813

Error Reading from a Pipe

void turtle (int gtot)
{
    int msg;
    fcntl(gtot,F_SETFL,O_NONBLOCK);
    read(gtot,&msg,4);

    gotoxy(12, 21); printf("The value of buffer for turtle is %d",msg);

    //react to god's message
    xcoor += msg;
    msg = 0;
            sleep(sleep_time);
 }

 void god (int gtot )
 {
        char choice, sign;
        int distance;
        scanf("%c",&choice);
        //choice = getchar();
        gotoxy(1,18);
        printf("Enter the distance which should be moved");
        fflush(stdout);
        gotoxy(50, 14);
        scanf ("%d", &distance);
        int newd = distance;
        //printf ("The distance that is to be moved by %d", distance);

        if (choice == 'h')
        {
            write(gtoh,&distance,4);
        }
        else if (choice == 't')
        {
            write(gtot,&newd,4);
            gotoxy(12,23);
                            printf("I am writing %d as the number", distance); 
                            fflush(stdout);
        }
        //printf("You chose %s", &choice);
        sleep(sleep_time);
    }
    main(){
int gtot[2];
pipe (gtot);
pid_turtle = fork ();
if (pid_turtle == 0)
  {
      close (gtot[1]);
      turtle (gtot[0]);
  }

pid_god = fork ();
if (pid_god == 0)
  {
      close (gtot[0]);
      god (gtot[1]);
  }
   }

When I write from the pipe from God function to the Turtle function. I expect it to return nothing when the user gives no input and the numbers when the user gives any. But the printf statement is printing outputs like

       The value of buffer for turtle is 0106368
       The value of buffer for turtle is 05291328

Which seems to me like the memory address of the number. What is the error that I am making in the program.

Upvotes: 1

Views: 2479

Answers (3)

Heath Hunnicutt
Heath Hunnicutt

Reputation: 19467

Several observations about your program:

In function turtle:

  1. You do not initialize the variable msg.
  2. You set the gtot file descriptor for O_NONBLOCK.
  3. BUT you do not check the return value of read.

This is a significant problem. read is returning immediately and you are printing the uninitialized value of msg.

  • The way you fork and close is also contributing. You have closed gtot[1] prior to fork-ing the "god" process. If you choose to use this one-parent of two-child-processes approach, don't close the file handles until you are done fork-ing.

  • Also, it appears that you intended for at least the turtle function, and probably the god function, to loop. As written, your turtle function will immediately exit: it has no loop and it performs read with the O_NONBLOCK flag set.

  • But wait, there is more. When you do call fcntl to set O_NONBLOCK, what you are doing is also resetting every flag other than O_NONBLOCK. Here is a function taken from the libc documentation which handles the other flags while setting or resetting the non-blocking flag:

/* Set the O_NONBLOCK flag of desc if value is nonzero, or clear the flag if value is 0. Return 0 on success, or -1 on error with errno set. */

int
set_nonblock_flag (int desc, int value)
{
  int oldflags = fcntl (desc, F_GETFL, 0);
  /* If reading the flags failed, return error indication now. */
  if (oldflags == -1)
    return -1;
  /* Set just the flag we want to set. */
  if (value != 0)
    oldflags |= O_NONBLOCK;
  else
    oldflags &= ~O_NONBLOCK;
  /* Store modified flag word in the descriptor. */
  return fcntl (desc, F_SETFL, oldflags);
}

There are some other things which could also be contributing to your problem:

  • It would be best to replace every occurence of "4" with sizeof(int) wherever you are calling read and write. It is possible that integers are 8 bytes on your machine (64 bit integer?), although pretty unlikely. In the future, it is more likely that int would be 8 bytes, and your code is very fragile in this regard.

There is also something "Strange" about your program that I am observing:

  • Why is the decimal output from printf being prefixed with a leading 0 (zero)? That would be an octal representation, but the printf specifier is not "%o". "%d" should not show leading zeros unless you use a width-specifier with a leading zero, a la "%08d". So I don't know what to make about that.

Upvotes: 3

koo5
koo5

Reputation: 485

you dont want to call fork twice. You also dont want to close the unused ends of the pipe:)

Upvotes: 2

Zan Lynx
Zan Lynx

Reputation: 54393

If this is Linux try using strace to see the exact data being written to the pipes.

If this is Solaris or Mac OS X try dtrace or dtruss.

On BSD I believe the command to view system calls is just truss.

These are very useful commands.

Upvotes: 1

Related Questions