tonythestark
tonythestark

Reputation: 553

Unix system calls : read/write and the buffer

I am writing a pretty simple script .

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


int main(){
        int pipefd[2];
        pid_t c;
        int value[2];
        c = fork();
        if(c<0){
                perror("in fork");
                exit(1);
        }
        if(c==0){
                printf("i am the child\n");
                int buf[2];
                buf[0]=3;
                buf[1]=0;
                write(pipefd[1], buf, 4);
                write(pipefd[1],buf+1,4);
                close(pipefd[1]);
                exit(0);
        }
          if (pipe(pipefd) == -1) {      /*UPDATE */
                        perror("pipe");   
                        exit(EXIT_FAILURE);
          }

        read(pipefd[0], value, 4);
        read(pipefd[0], value+1, 4);
        close(pipefd[0]);
        printf("%d %d\n", value[0], value[1]);
        exit(0);
}

What I intend to do is to achieve:

value[0] = buf[0]; value[1] = buf[1];

( and print those of course).

But all I get as a result is :

-1299582208 32766
i am the child

Because, I have ints, I assumed that each will hold 4 bytes. And I think that for an int array each element will holds 4 bytes. But clearly I am missing something. Any help?

Upvotes: 0

Views: 84

Answers (2)

Craig Estey
Craig Estey

Reputation: 33601

As I mentioned in my top comment: Where is the pipe syscall?

Without it, the write and read calls will probably fail because pipefd has random values.

So, the parent will never have value filled in correctly.

Because these [unitialized] values are on the stack, they will have random values, which is what you're seeing.

This is UB [undefined behavior].

Different systems/compilers may manipulate the stack differently, which is why you see different [yet still random] results on different configurations.

To fix, add the following above your fork call:

pipe(pipefd);

I downloaded, built, and ran your program. Before I added the fix, I got random values. After applying the fix, I get 3 0 as the output, which is what you expected/wanted.

Note: As others have mentioned, you could check the return codes for read and write. If you had, they might return -1 and put an error code in errno that would have helped you debug the issue.

Upvotes: 2

user3546408
user3546408

Reputation:

A very simple fix would be to put a sleep(1) call right above your read() calls - obviously this isn't a great solution.

An important early lesson in multi process programming and communications is "race conditions". Your fork'd child is executing before the parent, it seems. I bet if you ran this 20 times, you might get X number of times where it does what you want!

You cannot guarantee the order of execution. So a sleep(1) will suffice until you learn more advanced techniques on resource locking (mutexes, semaphores).

Upvotes: 1

Related Questions