sys_proc_create() can dup FGRPs (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 1 Jul 2014 22:55:40 +0000 (15:55 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 1 Jul 2014 22:55:40 +0000 (15:55 -0700)
9ns FGRPs were always being duped for all processes (fork and create), but VFS
ones were only duped for forks.  Now both 9ns and VFS behave the same way, and
you can pass a flag to have your entire FGRP, minus the CLOEXECs, duped from a
parent to a child on creation.  This happens implicitly in a fork().

Eventually, we'll have another dup call, say dup11345385(), that will allow a
parent to "dup2" specific FDs to its child.

Reinstall your kernel headers, or just:

$ cp kern/include/ros/procinfo.h \
  XCC_ROOT/install-x86_64-ros-gcc/x86_64-ros/sys-include/ros/procinfo.h

kern/include/ns.h
kern/include/process.h
kern/include/ros/procinfo.h
kern/src/ns/sysfile.c
kern/src/process.c
kern/src/syscall.c
tests/old/spawn.c
user/parlib/include/parlib.h
user/parlib/syscall.c

index bd8a09b..88dd5e7 100644 (file)
@@ -992,7 +992,7 @@ int sysiounit(int fd);
 void close_9ns_files(struct proc *p, bool only_cloexec);
 void print_chaninfo(struct chan *ch);
 void print_9ns_files(struct proc *p);
-int plan9setup(struct proc *new_proc, struct proc *parent);
+int plan9setup(struct proc *new_proc, struct proc *parent, int flags);
 int iseve(void);
 int fd_getfl(int fd);
 int fd_setfl(int fd, int flags);
index 3c61212..470d02f 100644 (file)
@@ -61,7 +61,7 @@ void proc_init(void);
 
 /* Process management: */
 struct proc *pid_nth(unsigned int n);
-error_t proc_alloc(struct proc **pp, struct proc *parent);
+error_t proc_alloc(struct proc **pp, struct proc *parent, int flags);
 void __proc_ready(struct proc *p);
 struct proc *proc_create(struct file *prog, char **argv, char **envp);
 int __proc_set_state(struct proc *p, uint32_t state) WRITES(p->state);
index a34e7f2..e54b184 100644 (file)
@@ -10,6 +10,9 @@
 #include <ros/arch/arch.h>
 #include <string.h>
 
+/* Process creation flags */
+#define PROC_DUP_FGRP                  1
+
 #define PROCINFO_MAX_ARGP 32
 #define PROCINFO_ARGBUF_SIZE 3072
 
index 7966bd8..94f477d 100644 (file)
@@ -1406,7 +1406,7 @@ void print_9ns_files(struct proc *p)
 
 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  Looks like we're
  * copying the fgrp, and sharing the pgrp. */
-int plan9setup(struct proc *new_proc, struct proc *parent)
+int plan9setup(struct proc *new_proc, struct proc *parent, int flags)
 {
        struct proc *old_current;
        struct kref *new_dot_ref;
@@ -1437,9 +1437,12 @@ int plan9setup(struct proc *new_proc, struct proc *parent)
                poperror();
                return 0;
        }
-       /* Copy semantics: do not change this without revisiting proc_destroy,
-        * close_9ns_files, and closefgrp. */
-       new_proc->fgrp = dupfgrp(new_proc, parent->fgrp);
+       /* When we use the old fgrp, we have copy semantics: do not change this
+        * without revisiting proc_destroy, close_9ns_files, and closefgrp. */
+       if (flags & PROC_DUP_FGRP)
+               new_proc->fgrp = dupfgrp(new_proc, parent->fgrp);
+       else
+               new_proc->fgrp = newfgrp();
        /* Shared semantics */
        kref_get(&parent->pgrp->ref, 1);
        new_proc->pgrp = parent->pgrp;
index 8fc1c9e..f7c617d 100644 (file)
@@ -294,7 +294,7 @@ static void proc_init_procdata(struct proc *p)
  * Errors include:
  *  - ENOFREEPID if it can't get a PID
  *  - ENOMEM on memory exhaustion */
-error_t proc_alloc(struct proc **pp, struct proc *parent)
+error_t proc_alloc(struct proc **pp, struct proc *parent, int flags)
 {
        error_t r;
        struct proc *p;
@@ -376,13 +376,24 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        p->open_files.max_fdset = NR_FILE_DESC_DEFAULT;
        p->open_files.fd = p->open_files.fd_array;
        p->open_files.open_fds = (struct fd_set*)&p->open_files.open_fds_init;
+       if (parent) {
+               if (flags & PROC_DUP_FGRP)
+                       clone_files(&parent->open_files, &p->open_files);
+       } else {
+               /* no parent, we're created from the kernel */
+               assert(insert_file(&p->open_files, dev_stdin,  0) == 0);
+               assert(insert_file(&p->open_files, dev_stdout, 0) == 1);
+               assert(insert_file(&p->open_files, dev_stderr, 0) == 2);
+       }
        /* Init the ucq hash lock */
        p->ucq_hashlock = (struct hashlock*)&p->ucq_hl_noref;
        hashlock_init_irqsave(p->ucq_hashlock, HASHLOCK_DEFAULT_SZ);
 
        atomic_inc(&num_envs);
        frontend_proc_init(p);
-       plan9setup(p, parent);
+       /* this does all the 9ns setup, much of which is done throughout this func
+        * for the VFS, including duping the fgrp */
+       plan9setup(p, parent, flags);
        devalarm_init(p);
        TAILQ_INIT(&p->abortable_sleepers);
        spinlock_init_irqsave(&p->abort_list_lock);
@@ -412,14 +423,10 @@ struct proc *proc_create(struct file *prog, char **argv, char **envp)
 {
        struct proc *p;
        error_t r;
-       if ((r = proc_alloc(&p, current)) < 0)
+       if ((r = proc_alloc(&p, current, 0 /* flags */)) < 0)
                panic("proc_create: %e", r);    /* one of 3 quaint usages of %e */
        procinfo_pack_args(p->procinfo, argv, envp);
        assert(load_elf(p, prog) == 0);
-       /* Connect to stdin, stdout, stderr */
-       assert(insert_file(&p->open_files, dev_stdin,  0) == 0);
-       assert(insert_file(&p->open_files, dev_stdout, 0) == 1);
-       assert(insert_file(&p->open_files, dev_stderr, 0) == 2);
        __proc_ready(p);
        return p;
 }
index c35ac01..0f2523c 100644 (file)
@@ -354,7 +354,7 @@ static pid_t sys_getpid(struct proc *p)
  * default, so it needs it's status to be changed so that the next call to
  * schedule() will try to run it.  TODO: take args/envs from userspace. */
 static int sys_proc_create(struct proc *p, char *path, size_t path_l,
-                           struct procinfo *pi)
+                           struct procinfo *pi, int flags)
 {
        int pid = 0;
        char *t_path;
@@ -373,10 +373,13 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
        /* TODO: need to split the proc creation, since you must load after setting
         * args/env, since auxp gets set up there. */
        //new_p = proc_create(program, 0, 0);
-       if (proc_alloc(&new_p, current)) {
+       if (proc_alloc(&new_p, current, flags)) {
                set_errstr("Failed to alloc new proc");
                goto mid_error;
        }
+       /* close the CLOEXEC ones, even though this isn't really an exec */
+       close_9ns_files(new_p, TRUE);
+       close_all_files(&new_p->open_files, TRUE);
        /* Set the argument stuff needed by glibc */
        if (memcpy_from_user_errno(p, new_p->procinfo->argp, pi->argp,
                                   sizeof(pi->argp))) {
@@ -393,10 +396,6 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
                goto late_error;
        }
        kref_put(&program->f_kref);
-       /* Connect to stdin, stdout, stderr (part of proc_create()) */
-       assert(insert_file(&new_p->open_files, dev_stdin,  0) == 0);
-       assert(insert_file(&new_p->open_files, dev_stdout, 0) == 1);
-       assert(insert_file(&new_p->open_files, dev_stderr, 0) == 2);
        __proc_ready(new_p);
        pid = new_p->pid;
        proc_decref(new_p);     /* give up the reference created in proc_create() */
@@ -508,7 +507,8 @@ static ssize_t sys_fork(env_t* e)
                return -1;
        }
        env_t* env;
-       assert(!proc_alloc(&env, current));
+       ret = proc_alloc(&env, current, PROC_DUP_FGRP);
+       assert(!ret);
        assert(env != NULL);
 
        env->heap_top = e->heap_top;
@@ -554,7 +554,6 @@ static ssize_t sys_fork(env_t* e)
        env->procdata->ldt = e->procdata->ldt;
        #endif
 
-       clone_files(&e->open_files, &env->open_files);
        /* FYI: once we call ready, the proc is open for concurrent usage */
        __proc_ready(env);
        proc_wakeup(env);
@@ -644,6 +643,7 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
        /* When we destroy our memory regions, accessing cur_sysc would PF */
        pcpui->cur_kthread->sysc = 0;
        unmap_and_destroy_vmrs(p);
+       /* close the CLOEXEC ones */
        close_9ns_files(p, TRUE);
        close_all_files(&p->open_files, TRUE);
        env_user_mem_free(p, 0, UMAPTOP);
index f2a46e9..73ffdee 100644 (file)
@@ -37,7 +37,8 @@ int main(int argc, char **argv, char **envp)
        printf("U: attempting to create and run hello\n");
        p_argv[0] = filename;
        printf("SPAWN, I'm pid %d, filename %s\n", getpid(), filename);
-       child_pid[0] = sys_proc_create(FILENAME, strlen(FILENAME), p_argv, p_envp);
+       child_pid[0] = sys_proc_create(FILENAME, strlen(FILENAME), p_argv, p_envp,
+                                      PROC_DUP_FGRP);
        if (child_pid[0] <= 0)
                printf("Failed to create the child\n");
        else
index 6e576e1..abfc4d4 100644 (file)
@@ -36,7 +36,8 @@ size_t      sys_getpcoreid(void);
 int         sys_getpid(void);
 int         sys_proc_destroy(int pid, int exitcode);
 void        sys_yield(bool being_nice);
-int         sys_proc_create(char *path, size_t path_l, char *argv[], char *envp[]);
+int         sys_proc_create(char *path, size_t path_l, char *argv[],
+                            char *envp[], int flags);
 int         sys_proc_run(int pid);
 ssize_t     sys_shared_page_alloc(void *COUNT(PGSIZE) *addr, pid_t p2, 
                                   int p1_flags, int p2_flags);
index d958dba..802d10f 100644 (file)
@@ -56,14 +56,15 @@ void sys_yield(bool being_nice)
        ros_syscall(SYS_yield, being_nice, 0, 0, 0, 0, 0);
 }
 
-int sys_proc_create(char *path, size_t path_l, char *argv[], char *envp[])
+int sys_proc_create(char *path, size_t path_l, char *argv[], char *envp[],
+                    int flags)
 {
        struct procinfo pi;
        if (procinfo_pack_args(&pi, argv, envp)) {
                errno = ENOMEM;
                return -1;
        }
-       return ros_syscall(SYS_proc_create, path, path_l, &pi, 0, 0, 0);
+       return ros_syscall(SYS_proc_create, path, path_l, &pi, flags, 0, 0);
 }
 
 int sys_proc_run(int pid)