summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_fork.c')
-rw-r--r--sys/kern/kern_fork.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 0ba17ce..1de3dc8 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -139,13 +139,6 @@ rfork(td, uap)
/* Don't allow kernel only flags. */
if ((uap->flags & RFKERNELONLY) != 0)
return (EINVAL);
- /*
- * Don't allow sharing of file descriptor table unless
- * RFTHREAD flag is supplied
- */
- if ((uap->flags & (RFPROC | RFTHREAD | RFFDG | RFCFDG)) ==
- RFPROC)
- return(EINVAL);
error = fork1(td, uap->flags, 0, &p2);
if (error == 0) {
td->td_retval[0] = p2 ? p2->p_pid : 0;
@@ -209,6 +202,7 @@ fork1(td, flags, pages, procp)
int ok;
static int pidchecked = 0;
struct filedesc *fd;
+ struct filedesc_to_leader *fdtol;
struct proc *p1 = td->td_proc;
struct thread *td2;
struct kse *ke2;
@@ -419,15 +413,40 @@ again:
/*
* Copy filedesc.
*/
- if (flags & RFCFDG)
+ if (flags & RFCFDG) {
fd = fdinit(td->td_proc->p_fd);
- else if (flags & RFFDG) {
+ fdtol = NULL;
+ } else if (flags & RFFDG) {
FILEDESC_LOCK(p1->p_fd);
fd = fdcopy(td->td_proc->p_fd);
FILEDESC_UNLOCK(p1->p_fd);
- } else
+ fdtol = NULL;
+ } else {
fd = fdshare(p1->p_fd);
-
+ if (p1->p_fdtol == NULL)
+ p1->p_fdtol =
+ filedesc_to_leader_alloc(NULL,
+ NULL,
+ p1->p_leader);
+ if ((flags & RFTHREAD) != 0) {
+ /*
+ * Shared file descriptor table and
+ * shared process leaders.
+ */
+ fdtol = p1->p_fdtol;
+ FILEDESC_LOCK(p1->p_fd);
+ fdtol->fdl_refcount++;
+ FILEDESC_UNLOCK(p1->p_fd);
+ } else {
+ /*
+ * Shared file descriptor table, and
+ * different process leaders
+ */
+ fdtol = filedesc_to_leader_alloc(p1->p_fdtol,
+ p1->p_fd,
+ p2);
+ }
+ }
/*
* Make a proc table entry for the new process.
* Start by zeroing the section of proc that is zero-initialized,
@@ -506,6 +525,7 @@ again:
if (p2->p_textvp)
VREF(p2->p_textvp);
p2->p_fd = fd;
+ p2->p_fdtol = fdtol;
PROC_UNLOCK(p1);
PROC_UNLOCK(p2);
OpenPOWER on IntegriCloud