Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_fork.c
Show First 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
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; | ||||
/* Don't allow kernel-only flags. */ | /* Don't allow kernel-only flags. */ | ||||
kib: You should check what you stated. If RFSPAWN is specified, all other flags must be cleared. | |||||
Done Inline ActionsRight, also going to revert the KERNELFLAG change and special case it here FOR RFPSPAWN kevans: Right, also going to revert the KERNELFLAG change and special case it here FOR RFPSPAWN | |||||
if ((uap->flags & RFKERNELONLY) != 0) | if ((uap->flags & RFKERNELONLY) != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* RFSPAWN must not appear with others */ | |||||
if ((uap->flags & RFSPAWN) != 0 && uap->flags != RFSPAWN) | |||||
return (EINVAL); | |||||
AUDIT_ARG_FFLAGS(uap->flags); | AUDIT_ARG_FFLAGS(uap->flags); | ||||
bzero(&fr, sizeof(fr)); | bzero(&fr, sizeof(fr)); | ||||
if ((uap->flags & RFSPAWN) != 0) { | |||||
fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; | |||||
fr.fr_flags2 = FR2_DROPSIG_CAUGHT; | |||||
} else | |||||
kibUnsubmitted Done Inline ActionsI prefer to put {} around branches consistently: if one branch requires it, then the other also get {}. kib: I prefer to put {} around branches consistently: if one branch requires it, then the other also… | |||||
fr.fr_flags = uap->flags; | fr.fr_flags = uap->flags; | ||||
fr.fr_pidp = &pid; | fr.fr_pidp = &pid; | ||||
error = fork1(td, &fr); | error = fork1(td, &fr); | ||||
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; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 282 Lines • ▼ Show 20 Lines | #endif | ||||
p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP); | p2->p_flag2 = p1->p_flag2 & (P2_NOTRACE | P2_NOTRACE_EXEC | P2_TRAPCAP); | ||||
p2->p_swtick = ticks; | p2->p_swtick = ticks; | ||||
if (p1->p_flag & P_PROFIL) | if (p1->p_flag & P_PROFIL) | ||||
startprofclock(p2); | startprofclock(p2); | ||||
if (fr->fr_flags & RFSIGSHARE) { | if (fr->fr_flags & RFSIGSHARE) { | ||||
p2->p_sigacts = sigacts_hold(p1->p_sigacts); | p2->p_sigacts = sigacts_hold(p1->p_sigacts); | ||||
} else { | } else { | ||||
sigacts_copy(newsigacts, p1->p_sigacts); | sigacts_copy(newsigacts, p1->p_sigacts); | ||||
Done Inline Actionsif (fr->fr_flags2 & FR2_SPAWN) == 0) That said, I do not think it is correct. You must copy and then reset sigactions to have any sane semantics. Most important, the already queued signals should be dropped, if any. kib: `if (fr->fr_flags2 & FR2_SPAWN) == 0)`
That said, I do not think it is correct. You must copy… | |||||
p2->p_sigacts = newsigacts; | p2->p_sigacts = newsigacts; | ||||
if ((fr->fr_flags2 & FR2_DROPSIG_CAUGHT) != 0) | |||||
sig_drop_caught(p2); | |||||
kibUnsubmitted Done Inline ActionsYour sig_drop_caught() requires p2->ps_mtx locked around the call. kib: Your sig_drop_caught() requires p2->ps_mtx locked around the call. | |||||
} | } | ||||
if (fr->fr_flags & RFTSIGZMB) | if (fr->fr_flags & RFTSIGZMB) | ||||
p2->p_sigparent = RFTSIGNUM(fr->fr_flags); | p2->p_sigparent = RFTSIGNUM(fr->fr_flags); | ||||
else if (fr->fr_flags & RFLINUXTHPN) | else if (fr->fr_flags & RFLINUXTHPN) | ||||
p2->p_sigparent = SIGUSR1; | p2->p_sigparent = SIGUSR1; | ||||
else | else | ||||
p2->p_sigparent = SIGCHLD; | p2->p_sigparent = SIGCHLD; | ||||
▲ Show 20 Lines • Show All 636 Lines • Show Last 20 Lines |
You should check what you stated. If RFSPAWN is specified, all other flags must be cleared.