+ long exit_state = 0;
+
+ if (utrace->u.live.signal != NULL)
+ /*
+ * There is a pending forced signal. It may have been
+ * left by an engine now detached. The empty utrace
+ * remains attached until it can be processed.
+ */
+ flags |= UTRACE_ACTION_QUIESCE;
+
+ /*
+ * If tracing was preventing a SIGCHLD or self-reaping
+ * and is no longer, we'll do that report or reaping now.
+ */
+ if (((tsk->utrace_flags &~ flags) & UTRACE_ACTION_NOREAP)
+ && tsk->exit_state && !utrace->u.exit.notified) {
+ BUG_ON(tsk->exit_state != EXIT_ZOMBIE);
+ /*
+ * While holding the utrace lock, mark that it's been done.
+ * For self-reaping, we need to change tsk->exit_state
+ * before clearing tsk->utrace_flags, so that the real
+ * parent can't see it in EXIT_ZOMBIE momentarily and reap it.
+ */
+ utrace->u.exit.notified = 1;
+ if (tsk->exit_signal == -1) {
+ exit_state = xchg(&tsk->exit_state, EXIT_DEAD);
+ BUG_ON(exit_state != EXIT_ZOMBIE);
+ exit_state = EXIT_DEAD;
+
+ /*
+ * Now that we've changed its state to DEAD,
+ * it's safe to install the new tsk->utrace_flags
+ * value without the UTRACE_ACTION_NOREAP bit set.
+ */
+ }
+ else if (thread_group_empty(tsk)) {
+ /*
+ * We need to prevent the real parent from reaping
+ * until after we've called do_notify_parent, below.
+ * It can get into wait_task_zombie any time after
+ * the UTRACE_ACTION_NOREAP bit is cleared. It's
+ * safe for that to do everything it does until its
+ * release_task call starts tearing things down.
+ * Holding tasklist_lock for reading prevents
+ * release_task from proceeding until we've done
+ * everything we need to do.
+ */
+ exit_state = EXIT_ZOMBIE;
+ read_lock(&tasklist_lock);
+ }