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.
This commit is contained in:
Sönke Ludwig 2018-10-30 12:27:01 +01:00
parent 8c4b147605
commit c3272f7d1f
2 changed files with 14 additions and 19 deletions

View file

@ -1350,9 +1350,6 @@ shared static this()
import std.concurrency; import std.concurrency;
scheduler = new VibedScheduler; scheduler = new VibedScheduler;
import vibe.core.sync : SpinLock;
SpinLock.setup();
} }
shared static ~this() shared static ~this()
@ -1377,10 +1374,6 @@ static this()
synchronized (st_threadsMutex) synchronized (st_threadsMutex)
if (!st_threads.any!(c => c.thread is thisthr)) if (!st_threads.any!(c => c.thread is thisthr))
st_threads ~= ThreadContext(thisthr); st_threads ~= ThreadContext(thisthr);
import vibe.core.sync : SpinLock;
SpinLock.setup();
} }
static ~this() static ~this()
@ -1463,7 +1456,10 @@ private extern(C) void onSignal(int signal)
nothrow { nothrow {
logInfo("Received signal %d. Shutting down.", signal); logInfo("Received signal %d. Shutting down.", signal);
atomicStore(st_term, true); 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) private extern(C) void onBrokenPipe(int signal)

View file

@ -1217,21 +1217,20 @@ package shared(Monitor!(T, M)) createMonitor(T, M)(M mutex)
package struct SpinLock { package struct SpinLock {
private shared int locked; private shared int locked;
static int threadID = 0; debug static int threadID;
static void setup()
{
import core.thread : Thread;
threadID = cast(int)cast(void*)Thread.getThis();
}
@safe nothrow @nogc shared: @safe nothrow @nogc shared:
bool tryLock() bool tryLock()
@trusted { @trusted {
assert(threadID != 0, "SpinLock.setup() was not called."); 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."); assert(atomicLoad(locked) != threadID, "Recursive lock attempt.");
return cas(&locked, 0, threadID); int tid = threadID;
} else int tid = 1;
return cas(&locked, 0, tid);
} }
void lock() void lock()
@ -1241,7 +1240,7 @@ package struct SpinLock {
void unlock() void unlock()
@trusted { @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); atomicStore(locked, 0);
} }
} }