From e4505e7cdd5414fc8ae7ab56aaac41319e6f69fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Thu, 3 Oct 2024 13:53:44 +0200 Subject: [PATCH] Avoid unnecessarily creating event driver instances in non-D threads. Using non-D threads to trigger ManualEvents should work without creating a thread instance of an event driver in the triggering thread. Using an event driver in such a thread leads to possible memory errors (because references to the driver instance are not visible to the GC) and leaks resources (event/socket pair handles) to the GC. --- source/vibe/core/sync.d | 50 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index 2ba5fac..a990464 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -1379,17 +1379,18 @@ struct ManualEvent { auto thisthr = Thread.getThis(); ThreadWaiter lw; - auto drv = eventDriver; - m_waiters.lock.active.iterate((ThreadWaiter w) { - debug (VibeMutexLog) () @trusted { logTrace("waiter %s", cast(void*)w); } (); - if (w.driver is drv) { - lw = w; - lw.addRef(); - } else { - w.triggerEvent(); - } - return true; - }); + if (auto drv = tryGetEventDriver) { + m_waiters.lock.active.iterate((ThreadWaiter w) { + debug (VibeMutexLog) () @trusted { logTrace("waiter %s", cast(void*)w); } (); + if (w.driver is drv) { + lw = w; + lw.addRef(); + } else { + w.triggerEvent(); + } + return true; + }); + } debug (VibeMutexLog) () @trusted { logTrace("lw %s", cast(void*)lw); } (); if (lw) { lw.emit(); @@ -1412,18 +1413,19 @@ struct ManualEvent { auto thisthr = Thread.getThis(); ThreadWaiter lw; - auto drv = eventDriver; - m_waiters.lock.active.iterate((ThreadWaiter w) { - () @trusted { logTrace("waiter %s", cast(void*)w); } (); - if (w.driver is drv) { - if (w.unused) return true; - lw = w; - lw.addRef(); - } else { - w.triggerEvent(); - } - return false; - }); + if (auto drv = tryGetEventDriver) { + m_waiters.lock.active.iterate((ThreadWaiter w) { + () @trusted { logTrace("waiter %s", cast(void*)w); } (); + if (w.driver is drv) { + if (w.unused) return true; + lw = w; + lw.addRef(); + } else { + w.triggerEvent(); + } + return false; + }); + } () @trusted { logTrace("lw %s", cast(void*)lw); } (); if (lw) { lw.emitSingle(); @@ -1502,7 +1504,7 @@ struct ManualEvent { private void acquireThreadWaiter(DEL)(scope DEL del) shared { ThreadWaiter w; - auto drv = eventDriver; + auto drv = tryGetEventDriver; with (m_waiters.lock) { active.iterate((aw) {