2

I want to run the child process earlier than the parent process. I just want to use execv call from the child process, So i am using vfork instead of fork.

But suppose execv fails and returns, i want to return non-zero value from the function in which i am calling vfork.

something like this,

int start_test()
{
  int err = 0;
  pid_t pid;
  pid = vfork();
  if(pid == 0) {
   execv(APP, ARGS);
   err = -1;
   _exit(1);
} else if(pid > 0) {
  //Do something else 
}
return err;
}

Is above code is proper, Or i should use some other mechanism to run child earlier than parent?

On some links, I have read that, We should not modify any parent resource in child process created through vfork(I am modifying err variable).

Jagdish
  • 1,848
  • 3
  • 22
  • 33
  • Relevant: http://stackoverflow.com/questions/4856255/the-difference-between-fork-vfork-exec-and-clone?rq=1 – Dummy00001 May 15 '15 at 07:58
  • the parent will execute to the end of the code. Then end of the code is returning a error condition (as if the fork() failed). suggest placing a 'else' statement before the 'return err;' statement, so the return err statement is only executed if the fork fails but not executed if the fork() was successful – user3629249 May 16 '15 at 02:22

2 Answers2

2

Is above code is proper?

No. The err variable is already in the child's memory, thus parent will not see its modification.

We should not modify any parent resource in child process created through vfork (I am modifying err variable).

The resource is outdated. Some *nix systems in the past tried to play tricks with the fork()/exec() pair, but generally those optimizations have largely backfired, resulting in unexpected, hard to reproduce problems. Which is why the vfork() was removed from the recent versions of POSIX.

Generally you can make this assumptions about vfork() on modern systems which support it: If the child does something unexpected by the OS, the child would be upgraded from vfork()ed to normal fork()ed one.

For example on Linux the only difference between fork() and vfork() is that in later case, more of the child's data are made into lazy COW data. The effect is that vfork() is slightly faster than fork(), but child is likely to sustain some extra performance penalty if it tries to access the yet-not-copied data, since they are yet to be duplicated from the parent. (Notice the subtle problem: parent can also modify the data. That would also trigger the COW and duplication of the data between parent and child processes.)

I just want to use execv call from the child process, So i am using vfork instead of fork.

The handling should be equivalent regardless of the vfork() vs fork(): child should return with a special exit code, and parent should do the normal waitpid() and check the exit status.

Otherwise, if you want to write a portable application, do not use the vfork(): it is not part of the POSIX standard.

P.S. This article might be also of interest. If you still want to use the vfork(), then read this scary official manpage.

Dummy00001
  • 16,630
  • 5
  • 41
  • 63
  • Nitpicking: Technically, `vfork()` was never part of POSIX, only of its superset XPG; [XPG7:2001](http://pubs.opengroup.org/onlinepubs/009695399/functions/vfork.html) page shows that with the `XSI` marking, and also stated the function was already obsolete in 2001; as you explained above, vfork was removed altogether in 2008. – AntoineL May 15 '15 at 08:44
  • @Dummy00001, If execv succeed, it will never return, and the child process will be replaced by the new process. Now if i call waitpid in the parent , my parent process will be block and waiting for the child's exit status, I dont want to block parent process, Is my understanding correct? – Jagdish May 15 '15 at 09:29
  • Also if execv fails, err variable modification is reflecting in the parent process also and , the function is returning the negative value. – Jagdish May 15 '15 at 09:30
  • If you do not want to block on `wait()`, then you have to install handler for `SIGCHLD` signal and handle it appropriately. – Dummy00001 May 15 '15 at 11:38
  • "Also if execv fails, err variable modification is reflecting in the parent process also" - that can't be. `err` is a local variable located on stack. Child and parent would have different stacks - because for example `execve()` call also requires the stack to be present. It would be a mess if two processes/threads used the same stack simultaneously. – Dummy00001 May 15 '15 at 11:40
  • if parent does not wait for child to exit, then child becomes a 'zombie'. Not a desirable situation and zombie processes are very difficult to eraticate by less that rebooting the system. – user3629249 May 16 '15 at 02:20
  • @user3629249 zombies processes are not dangerous at all. (1) They take very minimal system resources because (at very abstract level) the are only placeholders for the PID and the exit status. (2) They stay zombies only until the parent process finally terminates. After the parent dies, children are reparented to PID 1 (init) which has by design the `SIGCHLD`+`wait` handling specifically for that purpose. – Dummy00001 May 17 '15 at 07:41
  • @Dummy00001, This must be a change from when I last programmed professionally on a unix system. where the sys admin would 'slap my hand' about zombies that were around (and not removable) for days/weeks without a system reboot. And since my terminal was not a standalone system, rebooting would disrupt all the other users. Because I did not know better, in those days, I would create 20-50 zombies every day. – user3629249 May 20 '15 at 00:23
  • @Dummy00001: actually, on Linux, last I checked, `vfork()` shared memory between parent and child, just like threads, and suspended the parent until the child released its memory mappings, either via `execve()`, or `_exit()`. It also shares the stack, which creates some restrictions on what can be done (and forces the `vfork()` library call on at least some archs to be written on assembly, so thingies from the stack can be saved on registers, and restored later, so the parent doesn't have a corrupted stack frame). – ninjalj Mar 24 '17 at 11:57
  • @ninjalj, it changed couple of times throughout the Linux history, at least once after clone() syscall introduction and corresponding reimplementation of glibc innards. I'm lazy to check now, but most recent systems today, if your child process does something "inappropriate", would simple upgrade the process from light weight child to normal. Otherwise it would open a hole for new types of security vulnerabilities. – Dummy00001 Mar 25 '17 at 16:36
  • @Dummy00001: do you have a reference? As you can see at http://lxr.free-electrons.com/source/kernel/fork.c?v=4.10#L2020 `vfork()` just clones with shared VM (the same as threads, but threads share more things and do more setup), marked as CLONE_VFORK so the parent suspends until the child releases the VM, and SIGCHLD so the parent can `wait*()` to retrieve the exit status of the child. – ninjalj Mar 26 '17 at 11:55
  • @ninjajl, no I do not have reference, and actually the current version of man page on my Linux system disagrees with me. ... It changed at least 3-4 times since I started working with Linux. Otherwise, you can simply compare vfork man page of Solaris, HP-UX, Linux and BSD. Quick glimpse reveals that implementation differ greatly; vfork on Solaris is actually deprecated in favor of posix_spawn; and finally POSIXv7 has removed it altogether... – Dummy00001 Mar 27 '17 at 18:08
0

Yes. You should not modify the variable err. Use waitpid in the parent process to check the exit code of the child process. Also check the return value from execv and the errno variable(see man execv), to determine why your execv fails.