[PATCH 1/2] UTRACE_STOP race condition (updated)
Renzo Davoli
renzo at cs.unibo.it
Thu Mar 12 13:13:03 UTC 2009
Dear Roland, dear utrace developers,
I have updated my patch #1 (it solves the race condition on utrace_stop but
not the nesting issue) for the latest version of utrace.
I am trying to get the patches updated downloading, compiling and testing
the fixes every week or so...
Things would be easier if these patch could be merged in the mainstream ;-)
renzo
----
diff -Naur linux-2.6.29-rc7-git5-utrace/kernel/utrace.c linux-2.6.29-rc7-git5-utrace-p1/kernel/utrace.c
--- linux-2.6.29-rc7-git5-utrace/kernel/utrace.c 2009-03-12 11:00:09.000000000 +0100
+++ linux-2.6.29-rc7-git5-utrace-p1/kernel/utrace.c 2009-03-12 11:05:50.000000000 +0100
@@ -376,6 +376,13 @@
return killed;
}
+static void mark_engine_wants_stop(struct utrace_engine *engine);
+static void clear_engine_wants_stop(struct utrace_engine *engine);
+static bool engine_wants_stop(struct utrace_engine *engine);
+static void mark_engine_wants_resume(struct utrace_engine *engine);
+static void clear_engine_wants_resume(struct utrace_engine *engine);
+static bool engine_wants_resume(struct utrace_engine *engine);
+
/*
* Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up.
* @task == current, @utrace == current->utrace, which is not locked.
@@ -385,6 +392,7 @@
static bool utrace_stop(struct task_struct *task, struct utrace *utrace)
{
bool killed;
+ struct utrace_engine *engine, *next;
/*
* @utrace->stopped is the flag that says we are safely
@@ -406,7 +414,23 @@
return true;
}
- utrace->stopped = 1;
+ /* final check: it is really needed to stop? */
+ list_for_each_entry_safe(engine, next, &utrace->attached, entry) {
+ if ((engine->ops != &utrace_detached_ops) && engine_wants_stop(engine)) {
+ if (engine_wants_resume(engine)) {
+ clear_engine_wants_stop(engine);
+ clear_engine_wants_resume(engine);
+ }
+ else
+ utrace->stopped = 1;
+ }
+ }
+ if (unlikely(!utrace->stopped)) {
+ spin_unlock_irq(&task->sighand->siglock);
+ spin_unlock(&utrace->lock);
+ return false;
+ }
+
__set_current_state(TASK_TRACED);
/*
@@ -632,6 +656,7 @@
* to record whether the engine is keeping the target thread stopped.
*/
#define ENGINE_STOP (1UL << _UTRACE_NEVENTS)
+#define ENGINE_RESUME (1UL << (_UTRACE_NEVENTS+1))
static void mark_engine_wants_stop(struct utrace_engine *engine)
{
@@ -648,6 +673,21 @@
return (engine->flags & ENGINE_STOP) != 0;
}
+static void mark_engine_wants_resume(struct utrace_engine *engine)
+{
+ engine->flags |= ENGINE_RESUME;
+}
+
+static void clear_engine_wants_resume(struct utrace_engine *engine)
+{
+ engine->flags &= ~ENGINE_RESUME;
+}
+
+static bool engine_wants_resume(struct utrace_engine *engine)
+{
+ return (engine->flags & ENGINE_RESUME) != 0;
+}
+
/**
* utrace_set_events - choose which event reports a tracing engine gets
* @target: thread to affect
@@ -906,6 +946,10 @@
list_move(&engine->entry, &detached);
} else {
flags |= engine->flags | UTRACE_EVENT(REAP);
+ if (engine_wants_resume(engine)) {
+ clear_engine_wants_stop(engine);
+ clear_engine_wants_resume(engine);
+ }
wake = wake && !engine_wants_stop(engine);
}
}
@@ -1133,6 +1177,7 @@
* There might not be another report before it just
* resumes, so make sure single-step is not left set.
*/
+ mark_engine_wants_resume(engine);
if (likely(resume))
user_disable_single_step(target);
break;
More information about the utrace-devel
mailing list