From 15fa3651e11fbf36ab3649860a31be936919bb1e Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 24 Jul 2013 20:27:45 +0200 Subject: triton: Fix race upon termination The triton_terminate() function works by setting the need_close flag of each triton context, then queues this context for execution by a triton thread if not already running. But if the context is already being run by a triton thread, it may not notice that its need_close flag has been updated (this flag is only checked at the beginning of ctx_thread()). So if no other event wakes up that context (i.e. if ctx_thread() isn't run again), it will never terminate. This patch moves the need_close flag check at the end of ctx_thread() so that a triton context can take the need_close flag into account event if it's updated while running. The context spinlock is also used to protect the need_close flag as it is concurrently updated by triton_terminate(). Signed-off-by: Guillaume Nault --- accel-pppd/triton/triton.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/accel-pppd/triton/triton.c b/accel-pppd/triton/triton.c index cf06cea..6163b0a 100644 --- a/accel-pppd/triton/triton.c +++ b/accel-pppd/triton/triton.c @@ -184,11 +184,6 @@ static void ctx_thread(struct _triton_context_t *ctx) uint64_t tt; log_debug2("ctx %p %p: enter\n", ctx, ctx->thread); - if (ctx->need_close) { - if (ctx->ud->close) - ctx->ud->close(ctx->ud); - ctx->need_close = 0; - } while (1) { spin_lock(&ctx->lock); @@ -233,6 +228,17 @@ static void ctx_thread(struct _triton_context_t *ctx) break; } + spin_lock(&ctx->lock); + if (ctx->need_close) { + spin_unlock(&ctx->lock); + if (ctx->ud->close) { + ctx->ud->close(ctx->ud); + } + spin_lock(&ctx->lock); + ctx->need_close = 0; + } + spin_unlock(&ctx->lock); + log_debug2("ctx %p %p: exit\n", ctx, ctx->thread); } -- cgit v1.2.3