Module: Mongo::BackgroundThread Private
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
self,
Loggable
|
|
Defined in: | lib/mongo/background_thread.rb |
Overview
Do not start or stop background threads in finalizers. See jira.mongodb.org/browse/RUBY-2453 and bugs.ruby-lang.org/issues/16288. When interpreter exits, background threads are stopped first and finalizers are invoked next, and MRI’s internal data structures are basically corrupt at this point if threads are being referenced. Prior to interpreter shutdown this means threads cannot be stopped by objects going out of scope, but most likely the threads hold references to said objects anyway if work is being performed thus the objects wouldn’t go out of scope in the first place.
The run!, running? and stop! methods used to be part of the public API in some of the classes which now include this module. Therefore these methods must be considered part of the driver’s public API for backwards compatibility reasons. However using these methods outside of the driver is deprecated.
Constant Summary
Instance Attribute Summary
- #running? ⇒ Boolean readonly
Instance Method Summary
-
#run!
(also: #restart!)
Start the background thread.
-
#stop! ⇒ true | false
Stop the background thread and wait for to terminate for a reasonable amount of time.
-
#do_work
private
Internal use only
Override this method to do the work in the background thread.
-
#pre_stop
private
Internal use only
Override this method to perform additional signaling for the background thread to stop.
- #start! private Internal use only
-
#wait_for_stop
private
Internal use only
Waits for the thread to die, with a timeout.
Loggable
- Included
#log_debug | Convenience method to log debug messages with the standard prefix. |
#log_error | Convenience method to log error messages with the standard prefix. |
#log_fatal | Convenience method to log fatal messages with the standard prefix. |
#log_info | Convenience method to log info messages with the standard prefix. |
#log_warn | Convenience method to log warn messages with the standard prefix. |
#logger | Get the logger instance. |
#_mongo_log_prefix, #format_message |
Instance Attribute Details
#running? ⇒ Boolean
(readonly)
# File 'lib/mongo/background_thread.rb', line 63
def running? if @thread @thread.alive? else false end end
Instance Method Details
#do_work (private)
Override this method to do the work in the background thread.
# File 'lib/mongo/background_thread.rb', line 165
def do_work end
#pre_stop (private)
Override this method to perform additional signaling for the background thread to stop.
# File 'lib/mongo/background_thread.rb', line 170
def pre_stop end
#run! Also known as: #restart!
Start the background thread.
If the thread is already running, this method does nothing.
# File 'lib/mongo/background_thread.rb', line 46
def run! if @stop_requested && @thread wait_for_stop if @thread.alive? log_warn("Starting a new background thread in #{self}, but the previous background thread is still running") @thread = nil end @stop_requested = false end if running? @thread else start! end end
#start! (private)
[ GitHub ]# File 'lib/mongo/background_thread.rb', line 111
def start! @thread = Thread.new do catch(:done) do until @stop_requested do_work end end end end
#stop! ⇒ true
| false
Stop the background thread and wait for to terminate for a reasonable amount of time.
# File 'lib/mongo/background_thread.rb', line 77
def stop! # If the thread was not started, there is nothing to stop. # # Classes including this module may want to perform additional # cleanup, which they can do by overriding this method. return true unless @thread # Background threads generally perform operations in a loop. # This flag is meant to be checked on each iteration of the # working loops and the thread should stop working when this flag # is set. @stop_requested = true # Besides setting the flag, a particular class may have additional # ways of signaling the background thread to either stop working or # wake up to check the stop flag, for example, setting a semaphore. # This can be accomplished by providing the pre_stop method. pre_stop # Now we have requested the graceful termination, and we could wait # for the thread to exit on its own accord. A future version of the # driver may allow a certain amount of time for the thread to quit. # For now, we additionally use the Ruby machinery to request the thread # be terminated, and do so immediately. # # Note that this may cause the background thread to terminate in # the middle of an operation. @thread.kill wait_for_stop end
#wait_for_stop (private)
Waits for the thread to die, with a timeout.
Returns true if the thread died, false otherwise.
# File 'lib/mongo/background_thread.rb', line 124
def wait_for_stop # Wait for the thread to die. This is important in order to reliably # clean up resources like connections knowing that no background # thread will reconnect because it is still working. # # However, we do not want to wait indefinitely because in theory # a background thread could be performing, say, network I/O and if # the network is no longer available that could take a long time. start_time = Utils.monotonic_time ([0.1, 0.15] + [0.2] * 5 + [0.3] * 20).each do |interval| begin Timeout.timeout(interval) do @thread.join end break rescue ::Timeout::Error end end # Some driver objects can be reconnected, for backwards compatibiilty # reasons. Clear the thread instance variable to support this cleanly. if @thread.alive? log_warn("Failed to stop the background thread in #{self} in #{(Utils.monotonic_time - start_time).to_i} seconds: #{@thread.inspect} (thread status: #{@thread.status})") # On JRuby the thread may be stuck in aborting state # seemingly indefinitely. If the thread is aborting, consider it dead # for our purposes (we will create a new thread if needed, and # the background thread monitor will not detect the aborting thread # as being alive). if @thread.status == 'aborting' @thread = nil @stop_requested = false end false else @thread = nil @stop_requested = false true end end