Last active
September 7, 2022 10:22
-
-
Save bestie/b32cbec68ac4148441a42d02a1697de3 to your computer and use it in GitHub Desktop.
Ruby Thread#stop / #Thread.stop? doesn't work how you might think.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This does work because a my custom thread status is unambiguous. | |
# | |
# However, you may notice that setting the status and sleeping are not atomic. | |
require "net/http" | |
responses = [] | |
thread = Thread.new do | |
Thread.current[:what_i_am_doing] = "starting" | |
responses << Net::HTTP.get(URI.parse("https://zendesk.com")) | |
Thread.current[:what_i_am_doing] = "stopping" | |
sleep # sleep/wakeup seems nicer then stop/wakeup, also reflects value of Thread#status => "sleep" | |
Thread.current[:what_i_am_doing] = "just woke up" | |
responses << Net::HTTP.get(URI.parse("https://zendesk.com")) | |
Thread.current[:what_i_am_doing] = "all done" | |
end | |
until thread[:what_i_am_doing] == "stopping" # guaranteed to wait for the request to finish | |
sleep(0.001) | |
end | |
puts "#{responses.size == 1}: Thread has made the first request and stopped" | |
puts "#{thread.inspect.include?("sleep>")}: Thread is now having a regular sleep" | |
thread.wakeup | |
thread.join(_timeout = 5) # Hopefully that's long enough for the request | |
puts "#{responses.size == 2}: Thread made both requests" | |
puts "#{thread.inspect.include?("dead")}: Thread should be dead by now" | |
puts "#{thread[:what_i_am_doing] == "all done"}: Thread never woke up" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This doesn't always work because Thread#status is ambiguous | |
require "net/http" | |
responses = [] | |
thread = Thread.new do | |
Thread.current[:what_i_am_doing] = "starting" | |
responses << Net::HTTP.get(URI.parse("https://zendesk.com")) | |
Thread.current[:what_i_am_doing] = "stopping" | |
Thread.stop | |
Thread.current[:what_i_am_doing] = "just woke up" | |
responses << Net::HTTP.get(URI.parse("https://zendesk.com")) | |
Thread.current[:what_i_am_doing] = "all done" | |
end | |
until thread.stop? # Returns true when blocked on IO | |
sleep(0.001) # any amount of sleep helps thread switching but using next will be slower | |
end | |
thread.wakeup # Too early, the thread hasn't stopped yet | |
thread.join(_timeout = 5) # Give it as long as you like, it's stopped. | |
puts "#{responses.size == 1}: Thread only ever makes the first request" | |
puts "#{thread.inspect.include?("sleep_forever")}: Thread is now sleeping forever in stopped position" | |
puts "#{thread[:what_i_am_doing] == "stopping"}: Thread never woke up" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment