0

I'm trying to compile 2 executable files. One of them is sampler and other one is collector. Sampler must be called from a child of collector. Sampler one writes some datas to shared memory and collector should read it from shared memory. I am using execlp to call Sampler, but I think I am doing something wrong. It does not write anything with the code below. But when I execute Sampler manually it writes datas to shared memory, then when I execute the collector it can read the data correctly. In shortly execlp function does not call the Sampler properly. Why?

pid = fork();
if (pid == 0) {
  execlp("/home/gizux/Belgeler/ogr1grp14pro2/Sampler1","/home/gizux/Belgeler/ogr1grp14pro2/Sampler1", ShmID, NULL);
  exit(0);
}
else
{
//collector codes come here

}

If I don't use execlp() and put Sampler's codes to there, it's working .

pid = fork();
if (pid == 0) {
  ShmID = shmget(55667, 4*sizeof(int), IPC_CREAT | 0666);
  if (ShmID < 0) {
    printf("*** shmget error (server) ***\n");
    exit(1);
  }

  ShmPTR = (int *) shmat(ShmID, NULL, 0);
  if ((int) ShmPTR == -1) {
    printf("*** shmat error (server) ***\n");
    exit(1);
  }

  int random;

  random = rand()%100+1;

  ShmPTR[0] = r;
  ShmPTR[1] = random;

  r++;
  random = 0;
  printf("Sampler has filled %d %d in shared memory...\n",
        ShmPTR[0], ShmPTR[1]);

  exit(0);
}
else
{
//collector codes come here

}
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
gizux
  • 13
  • 2

2 Answers2

0

You should put some error reporting after your execlp call. (Remember: exec never returns if it's successful, so if you reach the statement after an exec, it failed.)

execlp(...);
perror("execlp failed");

You will probably find that it is failing with EFAULT. This will be because you are passing ShmID, an integer, as an argument. execlp only deals with strings. You will need to convert the integer to a string (e.g. with sprintf) and pass that to execlp. It will then appear in the other program's argv, where it of course will be a string, so you have to convert it back to a number.

  • Additionally, I am doubtful whether the scope of a shared-memory ID extends extends across `exec()`. Certainly, SysV shared-memory *attachments* do not survive an `exec()`. Separate processes normally map the same segment by passing the same *key* to `shmget()`. – John Bollinger May 11 '15 at 17:25
  • @Wumpus Q. Wumbley , I'm getting "bad address" execlp error. – gizux May 11 '15 at 17:31
  • @JohnBollinger You can get a list of keys *and* IDs with `ipcs` and then use a key *or* ID to remove one with `ipcrm` so I think the IDs must be consistent between processes. At least as long as the object is alive. When you make another one with the same key after deleting the first one, you probably get a new ID. –  May 11 '15 at 17:32
  • @JohnBollinger so you mean I should pass *shared memory key* to *sampler* instead of *shmid* ? – gizux May 11 '15 at 17:32
  • @gizux `strerror(EFAULT)` is `"Bad address"` so it's just like I said it would be. Now go ahead and apply the second part of my answer... –  May 11 '15 at 17:33
  • @gizux, yes, I am suggesting that you pass the key rather than the shmid. Or don't pass either if you consider the key to be a well-known quantity to both the sampler and the collector, as the code you present suggests you may be doing. – John Bollinger May 11 '15 at 17:38
  • @WumpusQ.Wumbley as you said I'm passing the key and casting it as char[] before passing to execlp() . And getting as argv[1] . EFAULT disappeared but this time it's not writing anything to shared memory. – gizux May 11 '15 at 17:46
  • sampler.c : http://paste.ubuntu.com/11082528/ main.c : http://paste.ubuntu.com/11082535/ result is like this : http://paste.ubuntu.com/11082562/ Notice, all these calls in an infinite loop, so every turn sampler will write a random number and collector will read, and it will go on like this until killing the process. – gizux May 11 '15 at 17:52
  • @JohnBollinger - the ID is what's used to attach (or remove, or modify) the shared memory segment. The shared memory ID is the unique identifier for each and every shared memory segment. The key is not guaranteed to be unique (e.g. `IPC_PRIVATE`). Passing the ID works fine - as long as the shared memory segment isn't removed. You can even use the ID returned from `shmget()` called with `IPC_PRIVATE` as the key to allow another process to attach to the shared memory segment. If that were not true, `ipcrm` would not be able to remove a shared memory segment created using an `IPC_PRIVATE` key. – Andrew Henle May 11 '15 at 19:08
  • Thanks, Andrew and Wumpus. I am schooled. – John Bollinger May 11 '15 at 19:14
0

Your execlp() call is wrong.

  execlp("/home/gizux/Belgeler/ogr1grp14pro2/Sampler1","/home/gizux/Belgeler/ogr1grp14pro2/Sampler1", ShmID, NULL);

Per the man page:

int execlp(const char *file, const char *arg, ...);

ShmID is not a const char *.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • thank you. We are working with gizux (owner of question) together. We fixed it but still it's not working. Please look for other answer's comments. Thank you. – Eray May 11 '15 at 19:04
  • You can also run your process under `strace` (assuming Linux) and capture the output of every system call your processes make. Something like this: `strace -f -o /path/to/output/file command args` where `command` and `args` are how you run your process. When you're done, the output file will contain all system calls made, with arguments and return values. Find all the `shmget()` and `shmat()` calls and make sure they're correct - using the same key, returning the same ID. – Andrew Henle May 11 '15 at 19:40