Use a custom nogc_assert in cleanup code.
Unfortunately the built-in assert GC allocates an exception, which means that if called directly or indirectly form a finalizer, the assertion will not become visible and instead an InvalidMemoryOperationError is thrown. This implements a custom nogc_assert() function that directly prints the assertion message and uses abort() to end the process.
This commit is contained in:
parent
acc35e1107
commit
df78af96bb
9 changed files with 45 additions and 17 deletions
|
@ -4,6 +4,7 @@ module eventcore.drivers.posix.events;
|
|||
import eventcore.driver;
|
||||
import eventcore.drivers.posix.driver;
|
||||
import eventcore.internal.consumablequeue : ConsumableQueue;
|
||||
import eventcore.internal.utils : nogc_assert;
|
||||
|
||||
version (linux) {
|
||||
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)
|
||||
{
|
||||
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 (!isInternal(descriptor))
|
||||
m_loop.m_waiterCount -= getSlot(descriptor).waiters.length;
|
||||
() @trusted nothrow {
|
||||
try .destroy(getSlot(descriptor).waiters);
|
||||
catch (Exception e) assert(false, e.msg);
|
||||
catch (Exception e) nogc_assert(false, e.msg);
|
||||
} ();
|
||||
version (linux) {
|
||||
m_loop.unregisterFD(descriptor, EventMask.read);
|
||||
|
@ -216,7 +217,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
|
|||
try {
|
||||
synchronized (m_eventsMutex)
|
||||
m_events.remove(rs);
|
||||
} catch (Exception e) assert(false, e.msg);
|
||||
} catch (Exception e) nogc_assert(false, e.msg);
|
||||
}
|
||||
m_loop.clearFD(descriptor);
|
||||
version (Posix) close(cast(int)descriptor);
|
||||
|
@ -228,7 +229,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
|
|||
|
||||
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(); } ();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ module eventcore.drivers.posix.signals;
|
|||
|
||||
import eventcore.driver;
|
||||
import eventcore.drivers.posix.driver;
|
||||
import eventcore.internal.utils : nogc_assert;
|
||||
|
||||
import std.algorithm.comparison : among;
|
||||
|
||||
|
@ -56,7 +57,7 @@ final class SignalFDEventDriverSignals(Loop : PosixEventLoop) : EventDriverSigna
|
|||
override bool releaseRef(SignalListenID 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
|
||||
m_loop.unregisterFD(fd, EventMask.read);
|
||||
m_loop.clearFD(fd);
|
||||
|
|
|
@ -804,7 +804,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets
|
|||
{
|
||||
import taggedalgebraic : hasType;
|
||||
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
|
||||
int base_refcount = slot.specific.hasType!StreamListenSocketSlot ? 1 : 0;
|
||||
if (--slot.common.refCount == base_refcount) {
|
||||
|
|
|
@ -3,6 +3,7 @@ module eventcore.drivers.posix.watchers;
|
|||
|
||||
import eventcore.driver;
|
||||
import eventcore.drivers.posix.driver;
|
||||
import eventcore.internal.utils : nogc_assert;
|
||||
|
||||
|
||||
final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriverWatchers
|
||||
|
@ -64,7 +65,7 @@ final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriver
|
|||
final override bool releaseRef(WatcherID 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
|
||||
m_loop.unregisterFD(fd, EventMask.read);
|
||||
m_loop.clearFD(fd);
|
||||
|
@ -281,10 +282,10 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
|
|||
|
||||
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 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)) {
|
||||
pt.dispose();
|
||||
m_pollers.remove(evt);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue