From 3c1654b2db5866394476de4fc0dff80e055bc376 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 9 Apr 2012 13:02:59 +0100 Subject: Bug 692979: Fix race condition in thread debugging. Bas Weelinck points out a potential problem with multiple threads starting up at the same time, running into a race condition in the thread debugging code. He suggests using an extra lock to avoid this, and indeed, it would be a simple way. I am reluctant to introduce an extra lock purely for this case though, so I've instead reused the ALLOC lock. This has the advantage of us not having to take the lock except in the 'first call with a new context' case. --- fitz/base_memory.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/base_memory.c b/fitz/base_memory.c index 32c7ff84..a30d75db 100644 --- a/fitz/base_memory.c +++ b/fitz/base_memory.c @@ -264,8 +264,23 @@ static int find_context(fz_context *ctx) return i; if (fz_lock_debug_contexts[i] == NULL) { - fz_lock_debug_contexts[i] = ctx; - return i; + int gottit; + /* We've not locked on this context before, so use + * this one for this new context. We might have other + * threads trying here too though so, so claim it + * atomically. No one has locked on this context + * before, so we are safe to take the ALLOC lock. */ + ctx->locks->lock(ctx->locks->user, FZ_LOCK_ALLOC); + /* If it's still free, then claim it as ours, + * otherwise we'll keep hunting. */ + if (fz_lock_debug_contexts[i] == NULL) + { + gottit = 1; + fz_lock_debug_contexts[i] = ctx; + } + ctx->locks->unlock(ctx->locks->user, FZ_LOCK_ALLOC); + if (gottit) + return i; } } return -1; -- cgit v1.2.3