LTTV_STATE_WAIT_FORK,
LTTV_STATE_WAIT_CPU,
LTTV_STATE_EXIT,
+ LTTV_STATE_ZOMBIE,
LTTV_STATE_WAIT,
LTTV_STATE_RUN;
guint process_hash(gconstpointer key)
{
- return ((const LttvProcessState *)key)->pid;
+ guint pid = ((const LttvProcessState *)key)->pid;
+ return (pid>>8 ^ pid>>4 ^ pid>>2 ^ pid) ;
}
* cases in the child's exit : when the parent ignores its children SIGCCHLD or
* has the flag SA_NOCLDWAIT. It can also happen when the child is part
* of a killed thread ground, but isn't the leader.
- *
- * This function is important : it removes the dead PID entry in the hash
- * table so there is no collision when the OS reuses PID.
*/
static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
{
g_assert(s->process->pid == 0);
}
- if(s->process->state->s != LTTV_STATE_EXIT) {
+ if(s->process->state->s == LTTV_STATE_EXIT) {
+ s->process->state->s = LTTV_STATE_ZOMBIE;
+ } else {
if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU;
else s->process->state->s = LTTV_STATE_WAIT;
} /* FIXME : we do not remove process here, because the kernel
* still has them : they may be zombies. We need to know
* exactly when release_task is executed on the PID to
- * know when the zombie is destroyed. We should rename STATE_EXIT
- * for STATE_ZOMBIE.
+ * know when the zombie is destroyed.
*/
//else
// exit_process(s, s->process);
{
LttField *f;
guint child_pid;
+ LttvProcessState *zombie_process;
/* Child PID */
f = trace_hook->f2;
child_pid = ltt_event_get_unsigned(s->parent.e, f);
- lttv_state_create_process(s, s->process, child_pid);
-
- return FALSE;
-#if 0
- LttField *f = ((LttvTraceHook *)hook_data)->f1;
+ zombie_process = lttv_state_find_process(s, child_pid);
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- guint child_pid;
-
- child_pid = ltt_event_get_unsigned(s->parent.e, f);
+ if(zombie_process != NULL) {
+ /* Reutilisation of PID. Only now we are sure that the old PID
+ * has been released. FIXME : sould know when release_task happens instead.
+ */
+ exit_process(s, zombie_process);
+ }
+ g_assert(s->process->pid != child_pid);
lttv_state_create_process(s, s->process, child_pid);
+
return FALSE;
-#endif //0
}
s->process->state->s = LTTV_STATE_EXIT;
}
return FALSE;
-
-#if 0
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- if(s->process != NULL) {
- s->process->state->s = LTTV_STATE_EXIT;
- }
- return FALSE;
-#endif //0
}
gboolean process(void *hook_data, void *call_data)
LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
LTTV_STATE_EXIT = g_quark_from_string("exiting");
+ LTTV_STATE_ZOMBIE = g_quark_from_string("zombie");
LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
LTTV_STATE_RUN = g_quark_from_string("running");
LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");