Skip to content

no mutex in shutdown #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
11 changes: 11 additions & 0 deletions example-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,14 @@ To run:
bundle
bundle exec clock
```

To test invocation of existing signal handlers, put this code at the very top of exe/clock:

```ruby
%w[INT TERM].each do |signal|
Signal.trap(signal) do
puts "This is a well-behaving #{signal} handler from outside of ruby-clock"
exit
end
end
```
29 changes: 22 additions & 7 deletions lib/ruby-clock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,37 @@ def wait_seconds
ENV['RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS']&.to_i || 29
end

def shutdown
puts "Shutting down ruby-clock. Waiting #{wait_seconds} seconds for jobs to finish..."
schedule.shutdown(wait: wait_seconds)
puts "...done 🐈️ 👋"
# shutdown is done async in a Thread because signal handlers should
# not have mutex locks created within them, which I believe can happen in
# the rufus shutdown process
def shutdown(old_handler=nil)
Thread.new do
sleep 0.1 # wait for trap block to exit
puts "Shutting down ruby-clock. Waiting #{wait_seconds} seconds for jobs to finish..."
schedule.shutdown(wait: wait_seconds)
puts "...done 🐈️ 👋"
if old_handler
puts "handing off shutdown to another signal handler..."
old_handler.call
else
exit
end
end
end

def listen_to_signals
signals = %w[INT TERM]
signals.each do |signal|
old_handler = Signal.trap(signal) do
shutdown
if old_handler.respond_to?(:call)
old_handler.call
shutdown(old_handler)
else
exit
shutdown
end

# keep this line here at the end, to serve as some degree of demonstration that
# the handler exited before shutdown begins
puts("received #{signal}") && STDOUT.flush
end
end
puts "RUBY_CLOCK_SHUTDOWN_WAIT_SECONDS is set to #{wait_seconds}"
Expand Down