Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_fork.c
Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
SDT_PROBE_DEFINE3(proc, , , create, "struct proc *", "struct proc *", "int"); | SDT_PROBE_DEFINE3(proc, , , create, "struct proc *", "struct proc *", "int"); | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct fork_args { | struct fork_args { | ||||
int dummy; | int dummy; | ||||
}; | }; | ||||
#endif | #endif | ||||
/* ARGSUSED */ | /** | ||||
int | * Helper for the pd- and v-fork calls containing the shared logic for fork, | ||||
sys_fork(struct thread *td, struct fork_args *uap) | * vfork, pdfork, and pdvfork. If `is_vfork` is set, then this does a | ||||
* [pd]vfork operation. If `outpid` is not null then this does a pd[v]fork | |||||
* operation. `pdfork_flags` contains the flags from a pdfork call and is | |||||
* ignured if `outpid` is null. | |||||
*/ | |||||
static int | |||||
do_pdvfork(struct thread *td, bool is_vfork, pid_t *outpid, int pdfork_flags) | |||||
{ | { | ||||
struct fork_req fr; | struct fork_req fr; | ||||
int error, pid; | int error, pid, fd; | ||||
bzero(&fr, sizeof(fr)); | bzero(&fr, sizeof(fr)); | ||||
fr.fr_flags = RFFDG | RFPROC; | fr.fr_flags = RFFDG | RFPROC | ((is_vfork) ? RFPPWAIT | RFMEM : 0); | ||||
if (outpid) { | |||||
fr.fr_flags |= RFPROCDESC; | |||||
fr.fr_pd_fd = &fd; | |||||
fr.fr_pd_flags = pdfork_flags; | |||||
} | |||||
fr.fr_pidp = &pid; | fr.fr_pidp = &pid; | ||||
error = fork1(td, &fr); | error = fork1(td, &fr); | ||||
/* | |||||
* It is necessary to return fd by reference because 0 is a valid file | |||||
* descriptor number, and the child needs to be able to distinguish | |||||
* itself from the parent using the return value. | |||||
*/ | |||||
if (error == 0) { | if (error == 0) { | ||||
td->td_retval[0] = pid; | td->td_retval[0] = pid; | ||||
td->td_retval[1] = 0; | td->td_retval[1] = 0; | ||||
if (outpid) { | |||||
error = copyout(&fd, outpid, sizeof(fd)); | |||||
} | } | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
/* ARGSUSED */ | |||||
int | |||||
sys_fork(struct thread *td, struct fork_args *uap) | |||||
{ | |||||
return (do_pdvfork(td, false, NULL, 0)); | |||||
} | |||||
/* ARGUSED */ | /* ARGUSED */ | ||||
int | int | ||||
sys_pdfork(struct thread *td, struct pdfork_args *uap) | sys_pdfork(struct thread *td, struct pdfork_args *uap) | ||||
{ | { | ||||
struct fork_req fr; | |||||
int error, fd, pid; | |||||
bzero(&fr, sizeof(fr)); | |||||
fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; | |||||
fr.fr_pidp = &pid; | |||||
fr.fr_pd_fd = &fd; | |||||
fr.fr_pd_flags = uap->flags; | |||||
AUDIT_ARG_FFLAGS(uap->flags); | AUDIT_ARG_FFLAGS(uap->flags); | ||||
/* | return (do_pdvfork(td, false, uap->fdp, uap->flags)); | ||||
* It is necessary to return fd by reference because 0 is a valid file | |||||
* descriptor number, and the child needs to be able to distinguish | |||||
* itself from the parent using the return value. | |||||
*/ | |||||
error = fork1(td, &fr); | |||||
if (error == 0) { | |||||
td->td_retval[0] = pid; | |||||
td->td_retval[1] = 0; | |||||
error = copyout(&fd, uap->fdp, sizeof(fd)); | |||||
} | } | ||||
return (error); | |||||
} | |||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
int | int | ||||
sys_vfork(struct thread *td, struct vfork_args *uap) | sys_vfork(struct thread *td, struct vfork_args *uap) | ||||
{ | { | ||||
struct fork_req fr; | |||||
int error, pid; | |||||
bzero(&fr, sizeof(fr)); | return (do_pdvfork(td, true, NULL, 0)); | ||||
fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; | |||||
fr.fr_pidp = &pid; | |||||
error = fork1(td, &fr); | |||||
if (error == 0) { | |||||
td->td_retval[0] = pid; | |||||
td->td_retval[1] = 0; | |||||
} | } | ||||
return (error); | |||||
/* ARGSUSED */ | |||||
int | |||||
sys_pdvfork(struct thread *td, struct pdvfork_args *uap) | |||||
{ | |||||
AUDIT_ARG_FFLAGS(uap->flags); | |||||
return (do_pdvfork(td, true, uap->fdp, uap->flags)); | |||||
} | } | ||||
int | int | ||||
sys_rfork(struct thread *td, struct rfork_args *uap) | sys_rfork(struct thread *td, struct rfork_args *uap) | ||||
{ | { | ||||
struct fork_req fr; | struct fork_req fr; | ||||
int error, pid; | int error, pid; | ||||
▲ Show 20 Lines • Show All 986 Lines • Show Last 20 Lines |