[PATCH] UTRACE_STOP race condition?
Renzo Davoli
renzo at cs.unibo.it
Fri Mar 6 10:35:44 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.
renzo
On Fri, Feb 13, 2009 at 09:29:25PM +0100, Renzo Davoli wrote:
> I have now a complete patch that seems to be quite stable.
> At least Kmview have passed through the tests without getting stuck randomly for the race condition.
>
---
--- kernel/utrace.c.mcgrath 2009-03-05 15:09:57.000000000 +0100
+++ kernel/utrace.c 2009-03-06 11:20:48.000000000 +0100
@@ -369,6 +369,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.
@@ -378,6 +385,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
@@ -399,7 +407,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);
/*
@@ -625,6 +649,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)
{
@@ -641,6 +666,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
@@ -891,6 +931,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);
}
}
@@ -1110,6 +1154,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