Rearm the CFFileDescriptor before each CFRunLoop run.
Instead of rearming from within the callback, this enables the callback before the event loop is run and before the kqueue is cleared. This at least heavily reduces the cases where the CFRunLoop hangs instead of reporting a pending kqueue event. For this reason, the safety timeout has been increased to 5 seconds.
This commit is contained in:
parent
f99ba6db49
commit
ab829efc7c
|
@ -31,7 +31,6 @@ final class CFRunLoopEventLoop : KqueueEventLoopBase {
|
||||||
m_kqueueDescriptor = CFFileDescriptorCreate(kCFAllocatorDefault,
|
m_kqueueDescriptor = CFFileDescriptorCreate(kCFAllocatorDefault,
|
||||||
m_queue, false, &processKqueue, &ctx);
|
m_queue, false, &processKqueue, &ctx);
|
||||||
|
|
||||||
CFFileDescriptorEnableCallBacks(m_kqueueDescriptor, CFOptionFlags.kCFFileDescriptorReadCallBack);
|
|
||||||
m_kqueueSource = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, m_kqueueDescriptor, 0);
|
m_kqueueSource = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, m_kqueueDescriptor, 0);
|
||||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_kqueueSource, kCFRunLoopDefaultMode);
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_kqueueSource, kCFRunLoopDefaultMode);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +39,8 @@ final class CFRunLoopEventLoop : KqueueEventLoopBase {
|
||||||
@trusted {
|
@trusted {
|
||||||
import std.algorithm.comparison : min;
|
import std.algorithm.comparison : min;
|
||||||
|
|
||||||
|
CFFileDescriptorEnableCallBacks(m_kqueueDescriptor, CFOptionFlags.kCFFileDescriptorReadCallBack);
|
||||||
|
|
||||||
// submit changes and process pending events
|
// submit changes and process pending events
|
||||||
auto kres = doProcessEventsBase(0.seconds);
|
auto kres = doProcessEventsBase(0.seconds);
|
||||||
if (kres) timeout = 0.seconds;
|
if (kres) timeout = 0.seconds;
|
||||||
|
@ -55,7 +56,7 @@ final class CFRunLoopEventLoop : KqueueEventLoopBase {
|
||||||
// events does not help (and is also eplicitly discouraged in
|
// events does not help (and is also eplicitly discouraged in
|
||||||
// Apple's documentation).
|
// Apple's documentation).
|
||||||
while (timeout > 0.seconds) {
|
while (timeout > 0.seconds) {
|
||||||
auto tol = min(timeout, 1.seconds);
|
auto tol = min(timeout, 5.seconds);
|
||||||
timeout -= tol;
|
timeout -= tol;
|
||||||
CFTimeInterval to = 1e-7 * tol.total!"hnsecs";
|
CFTimeInterval to = 1e-7 * tol.total!"hnsecs";
|
||||||
auto res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, to, true);
|
auto res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, to, true);
|
||||||
|
@ -63,6 +64,7 @@ final class CFRunLoopEventLoop : KqueueEventLoopBase {
|
||||||
return kres || res == CFRunLoopRunResult.kCFRunLoopRunHandledSource;
|
return kres || res == CFRunLoopRunResult.kCFRunLoopRunHandledSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFFileDescriptorEnableCallBacks(m_kqueueDescriptor, CFOptionFlags.kCFFileDescriptorReadCallBack);
|
||||||
kres = doProcessEventsBase(0.seconds);
|
kres = doProcessEventsBase(0.seconds);
|
||||||
if (kres) break;
|
if (kres) break;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +85,6 @@ final class CFRunLoopEventLoop : KqueueEventLoopBase {
|
||||||
CFOptionFlags callBackTypes, void* info)
|
CFOptionFlags callBackTypes, void* info)
|
||||||
{
|
{
|
||||||
auto this_ = () @trusted { return cast(CFRunLoopEventLoop)info; } ();
|
auto this_ = () @trusted { return cast(CFRunLoopEventLoop)info; } ();
|
||||||
auto res = this_.doProcessEventsBase(0.seconds);
|
this_.doProcessEventsBase(0.seconds);
|
||||||
() @trusted { CFFileDescriptorEnableCallBacks(this_.m_kqueueDescriptor, CFOptionFlags.kCFFileDescriptorReadCallBack); } ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue