2

I'm trying to have two child processes write two random integers to a shared memory, then have the parent read them. I cant seem to validate the writing as I get a segmentation fault whenever I try to access an array element in the parent process.

Trying to read from memory in child process right after writing does nothing.

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

int main(){
  srand(time(NULL)); 
  int pid2;
  key_t key = 12345;
  int shmid = shmget(key, 2 * sizeof(int), IPC_CREAT|IPC_EXCL|0666);
  int *array = (int *)shmat(shmid, 0, 0);
  int pid1 = fork();
//write first array element
  if (pid1 == 0){
    int n1 = rand() % 10;
    printf("I'm process number 1, my pid is %d and my number is %d\n", getpid(), n1);
    array[0] = n1;
    return 1;
  }
  if (pid1 > 0){
    int pid2 = fork();
    if (pid2 == 0){
//write second array element
      int n2 = rand() % 10;
      printf("I'm process number 2, my pid is %d and my number is %d\n", getpid(), n2);
      array[1] = n2;
      return 1;
    }
  }
  waitpid(pid1, NULL, 0);
  waitpid(pid2, NULL, 0);
//segmentation fault happens here
  printf("%d\n", array[0]);
  return 0;
}
  • regarding: `int pid2 = fork();` this makes `pid2` a local variable, totally unrelated to the initial declaration of `pid2` and the later reference: `waitpid(pid2, NULL, 0);` This is a serious error that needs to be corrected. Suggest: replacing: `int pid2 = fork();` with `pid2 = fork();` so it uses the 'function scope' variable instance rather than a variable that is only visible within the current code block – user3629249 May 02 '19 at 18:36
  • before the parent process exits, it should call `shmdt()` to detach the shared memory that was attached via `shmat()` – user3629249 May 02 '19 at 18:43
  • the function: `fork()` has 3 different returned values: The code is failing to check for a returned value that is <0, so the code (currently) acts as if the call(s) to `fork()` were always successful. That is a very risky assumption that the code should NOT make – user3629249 May 02 '19 at 18:46
  • @user3629249 missed that one, thanks! – Hellowuvrld May 02 '19 at 20:18

1 Answers1

3

You're not checking for a valid return value from shmget.

if (shmid<0){printf("shmget error");exit(1);};

If you did, you would find that the allocation was invalid, because that key_t already exists, try another one - or generate your own unique one:

key_t key = 1; 

or

key_t key = ftok("megasuperrandom",'a');

As per "man ftok":

Typically, a best-effort attempt combines the given proj_id byte, the lower 16 bits of the inode number, and the lower 8 bits of the device number into a 32-bit result. Collisions may easily happen, for example between files on /dev/hda1 and files on /dev/sda1.

So you will probably want to loop over some until you find one that works, as an alternative to using ftok().

Also, if you want the children to come up with different random numbers, you will likely want to use a different random function, or move srand() to each child.

Also, you might want to check "man waitpid". It doesn't wait until the process exits, it only waits for a changed state - which is unpredictable. If you want to make sure that the process exited, you will have to check the return status.

dagelf
  • 1,468
  • 1
  • 14
  • 25
  • Strangely enough, no string I gave ftok seemed to stop the segmentation fault, but `key_t key = 1; ` fixed it. Thanks! – Hellowuvrld May 02 '19 at 20:19