Properly refcnt child processes
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 18 Jan 2014 01:08:12 +0000 (17:08 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 18 Jan 2014 01:11:50 +0000 (17:11 -0800)
Parents hold a ref on their children.  We didn't incref for this.  For
forked processes, this was working, since we failed to decref.  Spawn,
which decreffed properly, blew up.

I think the ksched still had a copy of the proc, in this case, and it
tried to run it.  The kref check (can't incref when 0) caught this.

kern/src/process.c
kern/src/syscall.c

index ec5158d..b9c0174 100644 (file)
@@ -302,6 +302,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        p->exitcode = 1337;     /* so we can see processes killed by the kernel */
        if (parent) {
                p->ppid = parent->pid;
+               proc_incref(p, 1);      /* storing a ref in the parent */
                /* using the CV's lock to protect anything related to child waiting */
                cv_lock(&parent->child_wait);
                TAILQ_INSERT_TAIL(&parent->children, p, sibling_link);
@@ -875,7 +876,7 @@ int __proc_disown_child(struct proc *parent, struct proc *child)
        /* After this, the child won't be able to get more refs to us, but it may
         * still have some references in running code. */
        child->ppid = 0;
-       proc_decref(child);     /* ref that was keeping the child alive after dying */
+       proc_decref(child);     /* ref that was keeping the child alive on the list */
        return 0;
 }
 
index acebabe..98d70f4 100644 (file)
@@ -449,6 +449,7 @@ static ssize_t sys_fork(env_t* e)
 {
        struct proc *temp;
        int8_t state = 0;
+       int ret;
 
        // TODO: right now we only support fork for single-core processes
        if (e->state != PROC_RUNNING_S) {
@@ -513,7 +514,9 @@ static ssize_t sys_fork(env_t* e)
        // when the parent dies, or at least decref it
 
        printd("[PID %d] fork PID %d\n", e->pid, env->pid);
-       return env->pid;
+       ret = env->pid;
+       proc_decref(env);       /* give up the reference created in proc_alloc() */
+       return ret;
 }
 
 /* Load the binary "path" into the current process, and start executing it.