From c3272f7d1f4c9a91dd06faab3e0186075603d362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 30 Oct 2018 12:27:01 +0100 Subject: [PATCH] Fix assertion in SpinLock when called from a signal handler. Since the signal handler can be called in any thread of the application, it may happen so in a non-D thread where Thread.getThis() returns null. This change works around this and also removes the need to call SpinLock.setup on thread startup. --- source/vibe/core/core.d | 12 ++++-------- source/vibe/core/sync.d | 21 ++++++++++----------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/source/vibe/core/core.d b/source/vibe/core/core.d index 81266c2..d7f85e3 100644 --- a/source/vibe/core/core.d +++ b/source/vibe/core/core.d @@ -1350,9 +1350,6 @@ shared static this() import std.concurrency; scheduler = new VibedScheduler; - - import vibe.core.sync : SpinLock; - SpinLock.setup(); } shared static ~this() @@ -1377,10 +1374,6 @@ static this() synchronized (st_threadsMutex) if (!st_threads.any!(c => c.thread is thisthr)) st_threads ~= ThreadContext(thisthr); - - - import vibe.core.sync : SpinLock; - SpinLock.setup(); } static ~this() @@ -1463,7 +1456,10 @@ private extern(C) void onSignal(int signal) nothrow { logInfo("Received signal %d. Shutting down.", signal); atomicStore(st_term, true); - try st_threadsSignal.emit(); catch (Throwable) {} + try st_threadsSignal.emit(); + catch (Throwable th) { + logDebug("Failed to notify for event loop exit: %s", th.msg); + } } private extern(C) void onBrokenPipe(int signal) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index f84a455..9d1689b 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -1217,21 +1217,20 @@ package shared(Monitor!(T, M)) createMonitor(T, M)(M mutex) package struct SpinLock { private shared int locked; - static int threadID = 0; - - static void setup() - { - import core.thread : Thread; - threadID = cast(int)cast(void*)Thread.getThis(); - } + debug static int threadID; @safe nothrow @nogc shared: bool tryLock() @trusted { - assert(threadID != 0, "SpinLock.setup() was not called."); - assert(atomicLoad(locked) != threadID, "Recursive lock attempt."); - return cas(&locked, 0, threadID); + debug { + import core.thread : Thread; + if (threadID == 0) threadID = cast(int)cast(void*)Thread.getThis(); + if (threadID == 0) threadID = -1; // workaround for non-D threads + assert(atomicLoad(locked) != threadID, "Recursive lock attempt."); + int tid = threadID; + } else int tid = 1; + return cas(&locked, 0, tid); } void lock() @@ -1241,7 +1240,7 @@ package struct SpinLock { void unlock() @trusted { - assert(atomicLoad(locked) == threadID, "Unlocking spin lock that is not owned by the current thread."); + debug assert(atomicLoad(locked) == threadID, "Unlocking spin lock that is not owned by the current thread."); atomicStore(locked, 0); } }