Changeset View
Standalone View
sys/kern/kern_exit.c
Show First 20 Lines • Show All 992 Lines • ▼ Show 20 Lines | proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, | ||||
struct rusage *rup; | struct rusage *rup; | ||||
sx_assert(&proctree_lock, SA_XLOCKED); | sx_assert(&proctree_lock, SA_XLOCKED); | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
switch (idtype) { | switch (idtype) { | ||||
case P_ALL: | case P_ALL: | ||||
if (p->p_procdesc != NULL) { | if (p->p_procdesc == NULL || | ||||
(p->p_pptr == td->td_proc && | |||||
(p->p_flag & P_TRACED) != 0)) { | |||||
break; | |||||
kib: Wouldn't this cause return of the process status through wait(2) to parent (and not a debugger)… | |||||
Not Done Inline ActionsThe P_TRACED and P2_EXIT_TRACED flag would not be set if the child was returned. oshogbo: The P_TRACED and P2_EXIT_TRACED flag would not be set if the child was returned. | |||||
Done Inline ActionsSorry maybe I respond to quickly. Could you clarify a little bit more? Is this possible that we have attached a debugger and we reparented back to the parent? I didn't find such scenario in the code. oshogbo: Sorry maybe I respond to quickly. Could you clarify a little bit more?
Is this possible that… | |||||
Not Done Inline ActionsProcess is traced and exiting, which sets it P2_EXIT_TRACED flag. Debugger exits as well, which allows re-parenting of the child to the original parent. Then you get everything set up for returning status in wait(2) despite p_procdesc != NULL. Let me state it in other way: P2_EXIT_TRACED is not too different from not clearing P_TRACED at all. kib: Process is traced and exiting, which sets it P2_EXIT_TRACED flag. Debugger exits as well… | |||||
Done Inline ActionsYea you are right. I introduce a new flag to different our selves from the P_TRACED and not add our selves to the orphan list. I guess we should remove P2_EXIT_TRACED on re-parenting or detaching. oshogbo: Yea you are right. I introduce a new flag to different our selves from the P_TRACED and not add… | |||||
Not Done Inline ActionsI wonder do you need P2_EXIT_TRACED flag. Isn't the condition where P_TRACED or P2_EXIT_TRACED are set equivalent to the orphaned state of the child ? kib: I wonder do you need P2_EXIT_TRACED flag. Isn't the condition where P_TRACED or P2_EXIT_TRACED… | |||||
Done Inline ActionsI'm not sure. oshogbo: I'm not sure.
I think if the debugger is also a parent then we are not orphaned.
But maybe I… | |||||
Not Done Inline ActionsYou can check if parent == oparent additionally ? kib: You can check if parent == oparent additionally ? | |||||
Done Inline ActionsWhen we are parent and debugger then, I think, I wouldn't be still able to fetch last status when process exited and the P_TRACED flag was removed. If I would like to leave P_TRACED flag then I need to figure out how to inform kern_wait6 not to add it to the orphan list. oshogbo: When we are parent and debugger then, I think, I wouldn't be still able to fetch last status… | |||||
Not Done Inline ActionsCould we change ptrace() to add the child to the parent's orphan list even when the original parent is the debugger? markj: Could we change ptrace() to add the child to the parent's orphan list even when the original… | |||||
Done Inline ActionsI'm not sure about this approach. We may try to kill process twice first in the child list then in orphan lists. We can skip that if p_pid == q_oppid . oshogbo: I'm not sure about this approach. We may try to kill process twice first in the child list then… | |||||
Not Done Inline ActionsSorry, I'm not sure what you mean. exit() will send SIGKILL to children of the debugger, not orphans, but I guess you are referring to something else. IMO the "orphan" terminology is already non-intuitive: an orphan's parent may still be alive. Without having tried to implement it myself, I think having the debuggee always live on an orphan list is more consistent and easier to reason about. markj: Sorry, I'm not sure what you mean. exit() will send SIGKILL to children of the debugger, not… | |||||
Not Done Inline ActionsI have long wanted a 'p_debugees' list and a 'p_debugger' backpointer that was used when a debugger was detached and to not change the actual parent at all. I have had partial patches to do this in the past. The last time I brought this up when getppid was fixed to not report debuggers, kib@ convinced me that the new approach wouldn't really be any cleaner (you need workarounds to avoid reporting the status of a child with p_debugger != NULL to the "real" parent for example), but I still think it would probably be easier to reason about. Not sure if that is what you are asking about here? In case the parent is the debugger meaning the debugger explicitly used pdfork() to create the child, it seems like the debugger should be using pdwait() instead of wait(). OTOH, if the child process then uses pdfork() the debugger is only going to get pids back for that event unless we add additional changes (e.g. a new trace op) to get back a procdesc for the new process. I don't really think we want to target the case of a debugger using pdfork() to create debugees currently as that needs a lot more work. jhb: I have long wanted a 'p_debugees' list and a 'p_debugger' backpointer that was used when a… | |||||
Not Done Inline ActionsRight, the problem is to recognize the case where the parent is also the debugger. I think you're right that we can not worry about the case where the debugger used pdfork() to create the child. The main motivation here is to fix the case where some existing debugger (truss, gdb, etc.) is pointed at a pdfork() child. If we make that simplifying assumption, then it should be sufficient to check: if (p->p_procdesc == NULL || ((p->p_treeflag & P_TREE_ORPHANED) != 0 && p->p_pptr == td->td_proc) and maybe assert p->p_oppid != td->td_proc->p_pid in the latter case. markj: Right, the problem is to recognize the case where the parent is also the debugger.
I think… | |||||
} | |||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
return (0); | return (0); | ||||
} | |||||
break; | |||||
case P_PID: | case P_PID: | ||||
if (p->p_pid != (pid_t)id) { | if (p->p_pid != (pid_t)id) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
return (0); | return (0); | ||||
} | } | ||||
break; | break; | ||||
case P_PGID: | case P_PGID: | ||||
if (p->p_pgid != (pid_t)id) { | if (p->p_pgid != (pid_t)id) { | ||||
▲ Show 20 Lines • Show All 390 Lines • Show Last 20 Lines |
Wouldn't this cause return of the process status through wait(2) to parent (and not a debugger) if the process was already reparented back from the debugger to the original parent ?