/* 'rmp' now points to a child to be disinherited. */
rmp->mp_parent = INIT_PROC_NR;
+ /* If the process is making a VFS call, remember that we set
+ * a new parent. This prevents FORK from replying to the wrong
+ * parent upon completion.
+ */
+ if (rmp->mp_flags & VFS_CALL)
+ rmp->mp_flags |= NEW_PARENT;
+
/* Notify new parent. */
if (rmp->mp_flags & ZOMBIE)
check_parent(rmp, TRUE /*try_cleanup*/);
{
struct mproc *rmp;
endpoint_t proc_e;
- int r, proc_n;
+ int r, proc_n, new_parent;
/* PM_REBOOT is the only request not associated with a process.
* Handle its reply first.
if (!(rmp->mp_flags & VFS_CALL))
panic("handle_vfs_reply: reply without request: %d", call_nr);
- rmp->mp_flags &= ~VFS_CALL;
+ new_parent = rmp->mp_flags & NEW_PARENT;
+ rmp->mp_flags &= ~(VFS_CALL | NEW_PARENT);
if (rmp->mp_flags & UNPAUSED)
panic("handle_vfs_reply: UNPAUSED set on entry: %d", call_nr);
case PM_FORK_REPLY:
/* Schedule the newly created process ... */
- r = (OK);
+ r = OK;
if (rmp->mp_scheduler != KERNEL && rmp->mp_scheduler != NONE) {
r = sched_start_user(rmp->mp_scheduler, rmp);
}
/* If scheduling the process failed, we want to tear down the process
* and fail the fork */
- if (r != (OK)) {
+ if (r != OK) {
/* Tear down the newly created process */
rmp->mp_scheduler = NONE; /* don't try to stop scheduling */
exit_proc(rmp, -1, FALSE /*dump_core*/);
- /* Wake up the parent with a failed fork */
- setreply(rmp->mp_parent, -1);
-
+ /* Wake up the parent with a failed fork (unless dead) */
+ if (!new_parent)
+ setreply(rmp->mp_parent, -1);
}
else {
/* Wake up the child */
setreply(proc_n, OK);
- /* Wake up the parent */
- setreply(rmp->mp_parent, rmp->mp_pid);
+ /* Wake up the parent, unless the parent is already dead */
+ if (!new_parent)
+ setreply(rmp->mp_parent, rmp->mp_pid);
}
break;
#define SIGSUSPENDED 0x00100 /* set by SIGSUSPEND system call */
#define REPLY 0x00200 /* set if a reply message is pending */
#define VFS_CALL 0x00400 /* set if waiting for VFS (normal calls) */
+#define NEW_PARENT 0x00800 /* process's parent changed during VFS call */
#define UNPAUSED 0x01000 /* VFS has replied to unpause request */
#define PRIV_PROC 0x02000 /* system process, special privileges */
#define PARTIAL_EXEC 0x04000 /* process got a new map but no content */