Merge pull request #58 from vibe-d/nogc_assert

Use a custom nogc_assert in cleanup code.
This commit is contained in:
Sönke Ludwig 2018-03-11 20:30:50 +01:00 committed by GitHub
commit bcf178ef98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 45 additions and 17 deletions

View file

@ -4,6 +4,7 @@ module eventcore.drivers.posix.events;
import eventcore.driver; import eventcore.driver;
import eventcore.drivers.posix.driver; import eventcore.drivers.posix.driver;
import eventcore.internal.consumablequeue : ConsumableQueue; import eventcore.internal.consumablequeue : ConsumableQueue;
import eventcore.internal.utils : nogc_assert;
version (linux) { version (linux) {
nothrow @nogc extern (C) int eventfd(uint initval, int flags); nothrow @nogc extern (C) int eventfd(uint initval, int flags);
@ -199,13 +200,13 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
final override bool releaseRef(EventID descriptor) final override bool releaseRef(EventID descriptor)
{ {
assert(getRC(descriptor) > 0, "Releasing reference to unreferenced event FD."); nogc_assert(getRC(descriptor) > 0, "Releasing reference to unreferenced event FD.");
if (--getRC(descriptor) == 0) { if (--getRC(descriptor) == 0) {
if (!isInternal(descriptor)) if (!isInternal(descriptor))
m_loop.m_waiterCount -= getSlot(descriptor).waiters.length; m_loop.m_waiterCount -= getSlot(descriptor).waiters.length;
() @trusted nothrow { () @trusted nothrow {
try .destroy(getSlot(descriptor).waiters); try .destroy(getSlot(descriptor).waiters);
catch (Exception e) assert(false, e.msg); catch (Exception e) nogc_assert(false, e.msg);
} (); } ();
version (linux) { version (linux) {
m_loop.unregisterFD(descriptor, EventMask.read); m_loop.unregisterFD(descriptor, EventMask.read);
@ -216,7 +217,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
try { try {
synchronized (m_eventsMutex) synchronized (m_eventsMutex)
m_events.remove(rs); m_events.remove(rs);
} catch (Exception e) assert(false, e.msg); } catch (Exception e) nogc_assert(false, e.msg);
} }
m_loop.clearFD(descriptor); m_loop.clearFD(descriptor);
version (Posix) close(cast(int)descriptor); version (Posix) close(cast(int)descriptor);
@ -228,7 +229,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
private EventSlot* getSlot(EventID id) private EventSlot* getSlot(EventID id)
{ {
assert(id < m_loop.m_fds.length, "Invalid event ID."); nogc_assert(id < m_loop.m_fds.length, "Invalid event ID.");
return () @trusted { return &m_loop.m_fds[id].event(); } (); return () @trusted { return &m_loop.m_fds[id].event(); } ();
} }

View file

@ -3,6 +3,7 @@ module eventcore.drivers.posix.signals;
import eventcore.driver; import eventcore.driver;
import eventcore.drivers.posix.driver; import eventcore.drivers.posix.driver;
import eventcore.internal.utils : nogc_assert;
import std.algorithm.comparison : among; import std.algorithm.comparison : among;
@ -56,7 +57,7 @@ final class SignalFDEventDriverSignals(Loop : PosixEventLoop) : EventDriverSigna
override bool releaseRef(SignalListenID descriptor) override bool releaseRef(SignalListenID descriptor)
{ {
FD fd = cast(FD)descriptor; FD fd = cast(FD)descriptor;
assert(m_loop.m_fds[fd].common.refCount > 0, "Releasing reference to unreferenced event FD."); nogc_assert(m_loop.m_fds[fd].common.refCount > 0, "Releasing reference to unreferenced event FD.");
if (--m_loop.m_fds[fd].common.refCount == 1) { // NOTE: 1 because setNotifyCallback adds a second reference if (--m_loop.m_fds[fd].common.refCount == 1) { // NOTE: 1 because setNotifyCallback adds a second reference
m_loop.unregisterFD(fd, EventMask.read); m_loop.unregisterFD(fd, EventMask.read);
m_loop.clearFD(fd); m_loop.clearFD(fd);

View file

@ -804,7 +804,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets
{ {
import taggedalgebraic : hasType; import taggedalgebraic : hasType;
auto slot = () @trusted { return &m_loop.m_fds[fd]; } (); auto slot = () @trusted { return &m_loop.m_fds[fd]; } ();
assert(slot.common.refCount > 0, "Releasing reference to unreferenced socket FD."); nogc_assert(slot.common.refCount > 0, "Releasing reference to unreferenced socket FD.");
// listening sockets have an incremented the reference count because of setNotifyCallback // listening sockets have an incremented the reference count because of setNotifyCallback
int base_refcount = slot.specific.hasType!StreamListenSocketSlot ? 1 : 0; int base_refcount = slot.specific.hasType!StreamListenSocketSlot ? 1 : 0;
if (--slot.common.refCount == base_refcount) { if (--slot.common.refCount == base_refcount) {

View file

@ -3,6 +3,7 @@ module eventcore.drivers.posix.watchers;
import eventcore.driver; import eventcore.driver;
import eventcore.drivers.posix.driver; import eventcore.drivers.posix.driver;
import eventcore.internal.utils : nogc_assert;
final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriverWatchers final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriverWatchers
@ -64,7 +65,7 @@ final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriver
final override bool releaseRef(WatcherID descriptor) final override bool releaseRef(WatcherID descriptor)
{ {
FD fd = cast(FD)descriptor; FD fd = cast(FD)descriptor;
assert(m_loop.m_fds[fd].common.refCount > 0, "Releasing reference to unreferenced event FD."); nogc_assert(m_loop.m_fds[fd].common.refCount > 0, "Releasing reference to unreferenced event FD.");
if (--m_loop.m_fds[fd].common.refCount == 1) { // NOTE: 1 because setNotifyCallback increments the reference count if (--m_loop.m_fds[fd].common.refCount == 1) { // NOTE: 1 because setNotifyCallback increments the reference count
m_loop.unregisterFD(fd, EventMask.read); m_loop.unregisterFD(fd, EventMask.read);
m_loop.clearFD(fd); m_loop.clearFD(fd);
@ -281,10 +282,10 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
final override bool releaseRef(WatcherID descriptor) final override bool releaseRef(WatcherID descriptor)
{ {
assert(descriptor != WatcherID.invalid); nogc_assert(descriptor != WatcherID.invalid, "Invalid directory watcher ID released");
auto evt = cast(EventID)descriptor; auto evt = cast(EventID)descriptor;
auto pt = evt in m_pollers; auto pt = evt in m_pollers;
assert(pt !is null); nogc_assert(pt !is null, "Directory watcher polling thread does not exist");
if (!m_events.releaseRef(evt)) { if (!m_events.releaseRef(evt)) {
pt.dispose(); pt.dispose();
m_pollers.remove(evt); m_pollers.remove(evt);

View file

@ -5,6 +5,7 @@ module eventcore.drivers.timer;
import eventcore.driver; import eventcore.driver;
import eventcore.internal.dlist; import eventcore.internal.dlist;
import eventcore.internal.utils : nogc_assert;
final class LoopTimeoutTimerDriver : EventDriverTimers { final class LoopTimeoutTimerDriver : EventDriverTimers {
@ -143,8 +144,8 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
final override bool releaseRef(TimerID descriptor) final override bool releaseRef(TimerID descriptor)
{ {
assert(descriptor != TimerID.init, "Invalid timer ID."); nogc_assert(descriptor != TimerID.init, "Invalid timer ID.");
assert(descriptor in m_timers, "Unknown timer ID."); nogc_assert((descriptor in m_timers) !is null, "Unknown timer ID.");
if (descriptor !in m_timers) return true; if (descriptor !in m_timers) return true;
auto tm = m_timers[descriptor]; auto tm = m_timers[descriptor];

View file

@ -5,6 +5,7 @@ version (Windows):
import eventcore.driver; import eventcore.driver;
import eventcore.drivers.timer; import eventcore.drivers.timer;
import eventcore.internal.consumablequeue; import eventcore.internal.consumablequeue;
import eventcore.internal.utils : nogc_assert;
import eventcore.internal.win32; import eventcore.internal.win32;
import core.time : Duration; import core.time : Duration;
import taggedalgebraic; import taggedalgebraic;
@ -180,7 +181,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
package void freeSlot(HANDLE h) package void freeSlot(HANDLE h)
{ {
assert(h in m_handles, "Handle not in use - cannot free."); nogc_assert((h in m_handles) !is null, "Handle not in use - cannot free.");
m_handles.remove(h); m_handles.remove(h);
} }
} }
@ -214,7 +215,7 @@ private struct HandleSlot {
bool releaseRef(scope void delegate() @safe nothrow on_free) bool releaseRef(scope void delegate() @safe nothrow on_free)
{ {
assert(refCount > 0); nogc_assert(refCount > 0, "Releasing unreferenced slot.");
if (--refCount == 0) { if (--refCount == 0) {
on_free(); on_free();
return false; return false;

View file

@ -6,6 +6,7 @@ import eventcore.driver;
import eventcore.drivers.winapi.core; import eventcore.drivers.winapi.core;
import eventcore.internal.win32; import eventcore.internal.win32;
import eventcore.internal.consumablequeue; import eventcore.internal.consumablequeue;
import eventcore.internal.utils : nogc_assert;
final class WinAPIEventDriverEvents : EventDriverEvents { final class WinAPIEventDriverEvents : EventDriverEvents {
@ -108,7 +109,7 @@ final class WinAPIEventDriverEvents : EventDriverEvents {
override bool releaseRef(EventID descriptor) override bool releaseRef(EventID descriptor)
{ {
auto pe = descriptor in m_events; auto pe = descriptor in m_events;
assert(pe.refCount > 0); nogc_assert(pe.refCount > 0, "Releasing unreference event.");
if (--pe.refCount == 0) { if (--pe.refCount == 0) {
// make sure to not leak any waiter references for pending waits // make sure to not leak any waiter references for pending waits
foreach (i; 0 .. pe.waiters.length) foreach (i; 0 .. pe.waiters.length)

View file

@ -5,7 +5,7 @@ version (Windows):
import eventcore.driver; import eventcore.driver;
import eventcore.drivers.winapi.core; import eventcore.drivers.winapi.core;
import eventcore.internal.win32; import eventcore.internal.win32;
import eventcore.internal.utils : AlgebraicChoppedVector, print; import eventcore.internal.utils : AlgebraicChoppedVector, print, nogc_assert;
import std.socket : Address; import std.socket : Address;
private enum WM_USER_SOCKET = WM_USER + 1; private enum WM_USER_SOCKET = WM_USER + 1;
@ -697,7 +697,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
override bool releaseRef(SocketFD fd) override bool releaseRef(SocketFD fd)
{ {
import taggedalgebraic : hasType; import taggedalgebraic : hasType;
assert(m_sockets[fd].common.refCount > 0, "Releasing reference to unreferenced socket FD."); nogc_assert(m_sockets[fd].common.refCount > 0, "Releasing reference to unreferenced socket FD.");
if (--m_sockets[fd].common.refCount == 0) { if (--m_sockets[fd].common.refCount == 0) {
final switch (m_sockets[fd].specific.kind) with (SocketVector.FieldType) { final switch (m_sockets[fd].specific.kind) with (SocketVector.FieldType) {
case Kind.none: break; case Kind.none: break;

View file

@ -15,6 +15,28 @@ void print(ARGS...)(string str, ARGS args)
r.put('\n'); r.put('\n');
} }
private extern(C) Throwable.TraceInfo _d_traceContext(void* ptr = null);
void nogc_assert(bool cond, string message, string file = __FILE__, int line = __LINE__)
@trusted nothrow {
import core.stdc.stdlib : abort;
import std.stdio : stderr;
if (!cond) {
scope (exit) {
abort();
assert(false);
}
stderr.writefln("Assertion failure @%s(%s): %s", file, line, message);
stderr.writeln("------------------------");
if (auto info = _d_traceContext(null)) {
foreach (s; info)
stderr.writeln(s);
} else stderr.writeln("no stack trace available");
}
}
struct StdoutRange { struct StdoutRange {
@safe: @nogc: nothrow: @safe: @nogc: nothrow:
import core.stdc.stdio; import core.stdc.stdio;