Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/crystal/event_loop/iocp.cr
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ class Crystal::EventLoop::IOCP < Crystal::EventLoop
fiber = timer.value.fiber

case timer.value.type
in .sleep?
# nothing to do
in .timeout?
in .sleep?, .timeout?
timer.value.timed_out!
in .select_timeout?
return unless select_action = fiber.timeout_select_action
Expand Down Expand Up @@ -188,6 +186,15 @@ class Crystal::EventLoop::IOCP < Crystal::EventLoop
timer = Timer.new(:sleep, Fiber.current, duration)
add_timer(pointerof(timer))
Fiber.suspend

# safety check
return if timer.timed_out?

# try to avoid a double resume if possible, but another thread might be
# running the evloop and dequeue the event in parallel, so a "can't resume
# dead fiber" can still happen in a MT execution context.
delete_timer(pointerof(timer))
raise "BUG: #{timer.fiber} called sleep but was manually resumed before the timer expired!"
end

# Suspend the current fiber for *duration* and returns true if the timer
Expand Down
11 changes: 10 additions & 1 deletion src/crystal/event_loop/polling.cr
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ abstract class Crystal::EventLoop::Polling < Crystal::EventLoop
event = Event.new(:sleep, Fiber.current, timeout: duration)
add_timer(pointerof(event))
Fiber.suspend

# safety check
return if event.timed_out?

# try to avoid a double resume if possible, but another thread might be
# running the evloop and dequeue the event in parallel, so a "can't resume
# dead fiber" can still happen in a MT execution context.
delete_timer(pointerof(event))
raise "BUG: #{event.fiber} called sleep but was manually resumed before the timer expired!"
end

def create_timeout_event(fiber : Fiber) : FiberEvent
Expand Down Expand Up @@ -551,7 +560,7 @@ abstract class Crystal::EventLoop::Polling < Crystal::EventLoop
return unless select_action.time_expired?
fiber.@timeout_event.as(FiberEvent).clear
when .sleep?
# nothing to do
event.value.timed_out!
else
raise RuntimeError.new("BUG: unexpected event in timers: #{event.value}%s\n")
end
Expand Down