Reputation: 1207
I'm having some issues understanding fork()
in linux.
What is confusing me is if a parent forks a child process and that child calls execl()
and
execl()
doesn't return and the parent process waits on the child to exit, will the system then
hang?
Thanks in advance for any help.
Here's a code example from mdadm. So in the child process after execl()
there is exit(1)
.
If execl()
doesn't return then will exit(0)
ever execute? If not then the parent will wait indefinitely? Am I right here?
if (!check_env("MDADM_NO_SYSTEMCTL"))
switch(fork()) {
case 0:
/* FIXME yuk. CLOSE_EXEC?? */
skipped = 0;
for (i = 3; skipped < 20; i++)
if (close(i) < 0)
skipped++;
else
skipped = 0;
/* Don't want to see error messages from
* systemctl. If the service doesn't exist,
* we start mdmon ourselves.
*/
close(2);
open("/dev/null", O_WRONLY);
snprintf(pathbuf, sizeof(pathbuf), "mdmon@%s.service",
devnm);
status = execl("/usr/bin/systemctl", "systemctl",
"start",
pathbuf, NULL);
status = execl("/bin/systemctl", "systemctl", "start",
pathbuf, NULL);
exit(1);
case -1: pr_err("cannot run mdmon. "
"Array remains readonly\n");
return -1;
default: /* parent - good */
pid = wait(&status);
if (pid >= 0 && status == 0)
return 0;
}
Upvotes: 0
Views: 320
Reputation: 70206
First of all, note that execl
never returns (except if there is an error, which means execl
failed, i.e. it did "nothing" -- the child process still executes in the same module).
If the parent process waits for a child process to exit, then it will obviously block doing so. That is however expected behavior and it is not the same as "the system hangs". The system does not hang.
EDIT:
Concerning the code posted in the edited question: First, an [almost] exact duplicate of the process is created using fork
. Actually, one doesn't care about creating a duplicate, but one really wants to create a new process. However, under Unix, new processes are forked, not created from scratch.
Then follow two calls to execl
. Normally, the first one should already never return. Instead, the executable systemctl
will be loaded to replace the child process, and the child process will continue running from the entry point of systemctl
(this is a very simplified description, but it's essentially that).
Thus systemctl
will run, as a "new" independent process (in reality, it "stole" the forked process!), and it will (hopefully) eventually exit, which causes the parent process to return from wait
.
It may however happen that systemctl
cannot be found in /usr/bin
(or some other error occurs). For that case, the programmer of the above code makes another attempt at loading systemctl
from /bin
. Again, if this works, execl
will not return, but the code in systemctl
will execute and eventually exit. The parent process will then unblock from wait
.
Lastly, if that second call to execl
also fails (i.e. returns), the author gives up and simply calls exit(1)
, which returns a non-zero "error" code to the parent waking from wait
.
Upvotes: 2
Reputation: 36441
If exec
doesn't return, that means that the process is executing some (new) code. The new code fully replace the old one, so returning from a successful exec
is nonsense as the call to exec
is in the old code.
During this time the parent process is wait
ing the end of its child's execution. So the parent will be blocked until the child terminates.
Upvotes: 2
Reputation: 1
No. Every process is started using a fork() call and then the child doing a call from exec() family {see man for execl, execlp, execle, execv, execvp, execvpe}. The first process launched after boot is "init" and all processes can be traced back to "init" using their "ppid".
Upvotes: 0
Reputation: 41542
If a process is waiting on another process, and that other process calls exec(), the process that gets exec'd is now the process the first process is waiting for. So the system won't hang, and the first process will continue executing if/when the exec'd process exits.
Upvotes: 1