Sync fork/exec() with updates to procinfo/procdata
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 13 Oct 2015 04:40:26 +0000 (21:40 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 14 Oct 2015 20:50:10 +0000 (16:50 -0400)
The pipetest added in the previous commit exposes a bug with not copying
enough data from procinfo/procdata into a forked process in cases where
we don't exec after the fork. This commit updates the fork and exec code
to make sure that the relevant fields in procinfo/procdata are copied
over properly on a fork. If we do end up execing, these fields are
reinitialized to their initial values.

Signed-off-by: Kevin Klues <klueska@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/process.h
kern/src/process.c
kern/src/syscall.c

index a6e345f..6e1c636 100644 (file)
@@ -61,6 +61,8 @@ extern spinlock_t pid_hash_lock;
 /* Initialization */
 void proc_init(void);
 void proc_set_progname(struct proc *p, char *name);
+void proc_init_procinfo(struct proc* p);
+void proc_init_procdata(struct proc* p);
 
 /* Process management: */
 struct proc *pid_nth(unsigned int n);
index f7e9059..7640941 100644 (file)
@@ -263,7 +263,7 @@ void proc_set_progname(struct proc *p, char *name)
 }
 
 /* Be sure you init'd the vcore lists before calling this. */
-static void proc_init_procinfo(struct proc* p)
+void proc_init_procinfo(struct proc* p)
 {
        p->procinfo->pid = p->pid;
        p->procinfo->ppid = p->ppid;
@@ -285,7 +285,7 @@ static void proc_init_procinfo(struct proc* p)
        }
 }
 
-static void proc_init_procdata(struct proc *p)
+void proc_init_procdata(struct proc *p)
 {
        memset(p->procdata, 0, sizeof(struct procdata));
        /* processes can't go into vc context on vc 0 til they unset this.  This is
index 18dcdb1..22a9841 100644 (file)
@@ -703,8 +703,6 @@ static ssize_t sys_fork(env_t* e)
        assert(env != NULL);
        proc_set_progname(env, e->progname);
 
-       env->heap_top = e->heap_top;
-       env->ppid = e->pid;
        disable_irqsave(&state);        /* protect cur_ctx */
        /* Can't really fork if we don't have a current_ctx to fork */
        if (!current_ctx) {
@@ -738,12 +736,14 @@ static ssize_t sys_fork(env_t* e)
        finish_current_sysc(0);
        switch_back(env, temp);
 
+       /* Copy some state from the original proc into the new proc. */
+       env->heap_top = e->heap_top;
+       env->env_flags = e->env_flags;
+
        /* In general, a forked process should be a fresh process, and we copy over
         * whatever stuff is needed between procinfo/procdata. */
-       #ifdef CONFIG_X86
-       /* new guy needs to know about ldt (everything else in procdata is fresh */
-       env->procdata->ldt = e->procdata->ldt;
-       #endif
+       *env->procdata = *e->procdata;
+       env->procinfo->heap_bottom = e->procinfo->heap_bottom;
 
        /* FYI: once we call ready, the proc is open for concurrent usage */
        __proc_ready(env);
@@ -846,10 +846,8 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
        /* This is the point of no return for the process. */
        /* progname is argv0, which accounts for symlinks */
        proc_set_progname(p, argc ? argv[0] : NULL);
-       #ifdef CONFIG_X86
-       /* clear this, so the new program knows to get an LDT */
-       p->procdata->ldt = 0;
-       #endif
+       proc_init_procdata(p);
+       p->procinfo->heap_bottom = 0;
        /* When we destroy our memory regions, accessing cur_sysc would PF */
        pcpui->cur_kthread->sysc = 0;
        unmap_and_destroy_vmrs(p);