Skip to content

Commit 4a16092

Browse files
committed
Remove AtExit code
Following #840 which allowed all threads created by concurrent-ruby to be marked as daemon -- specifically in JRuby; the "AtExit" handling is no longer needed. Delete all references to "AtExit" and replace it with clearer documentation that the users can select whether the threads started shall be marked as daemon threads. > When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class). > The Java Virtual Machine continues to execute threads until either of the following occurs: > > 1. The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place. > 2. All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.
1 parent 94a2a9a commit 4a16092

File tree

6 files changed

+9
-155
lines changed

6 files changed

+9
-155
lines changed

lib/concurrent-ruby/concurrent/configuration.rb

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
require 'concurrent/concern/logging'
66
require 'concurrent/executor/immediate_executor'
77
require 'concurrent/executor/cached_thread_pool'
8-
require 'concurrent/utility/at_exit'
98
require 'concurrent/utility/processor_counter'
109

1110
module Concurrent
@@ -112,24 +111,6 @@ def self.global_logger=(value)
112111
GLOBAL_IMMEDIATE_EXECUTOR = ImmediateExecutor.new
113112
private_constant :GLOBAL_IMMEDIATE_EXECUTOR
114113

115-
# Disables AtExit handlers including pool auto-termination handlers.
116-
# When disabled it will be the application programmer's responsibility
117-
# to ensure that the handlers are shutdown properly prior to application
118-
# exit by calling `AtExit.run` method.
119-
#
120-
# @note this option should be needed only because of `at_exit` ordering
121-
# issues which may arise when running some of the testing frameworks.
122-
# E.g. Minitest's test-suite runs itself in `at_exit` callback which
123-
# executes after the pools are already terminated. Then auto termination
124-
# needs to be disabled and called manually after test-suite ends.
125-
# @note This method should *never* be called
126-
# from within a gem. It should *only* be used from within the main
127-
# application and even then it should be used only when necessary.
128-
#
129-
def self.disable_at_exit_handlers!
130-
AT_EXIT.enabled = false
131-
end
132-
133114
# Global thread pool optimized for short, fast *operations*.
134115
#
135116
# @return [ThreadPoolExecutor] the thread pool

lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'concurrent/errors'
22
require 'concurrent/executor/executor_service'
33
require 'concurrent/synchronization'
4-
require 'concurrent/utility/at_exit'
54

65
module Concurrent
76

@@ -18,6 +17,8 @@ class AbstractExecutorService < Synchronization::LockableObject
1817

1918
attr_reader :name
2019

20+
attr_accessor :ns_auto_terminate
21+
2122
# Create a new thread pool.
2223
def initialize(opts = {}, &block)
2324
super(&nil)
@@ -119,25 +120,8 @@ def ns_kill_execution
119120
end
120121

121122
def ns_auto_terminate?
122-
!!@auto_terminate
123-
end
124-
125-
def ns_auto_terminate=(value)
126-
case value
127-
when true
128-
AT_EXIT.add(self) { terminate_at_exit }
129-
@auto_terminate = true
130-
when false
131-
AT_EXIT.delete(self)
132-
@auto_terminate = false
133-
else
134-
raise ArgumentError
135-
end
123+
!!ns_auto_terminate
136124
end
137125

138-
def terminate_at_exit
139-
kill # TODO be gentle first
140-
wait_for_termination(10)
141-
end
142126
end
143127
end

lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,7 @@ module Concurrent
121121
# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at
122122
# any one time. When the queue size reaches `max_queue` and no new threads can be created,
123123
# subsequent tasks will be rejected in accordance with the configured `fallback_policy`.
124-
# * `auto_terminate`: When true (default) an `at_exit` handler will be registered which
125-
# will stop the thread pool when the application exits. See below for more information
126-
# on shutting down thread pools.
124+
# * `auto_terminate`: When true (default), the threads started will be marked as daemon.
127125
# * `fallback_policy`: The policy defining how rejected tasks are handled.
128126
#
129127
# Three fallback policies are supported:
@@ -148,16 +146,12 @@ module Concurrent
148146
#
149147
# On some runtime platforms (most notably the JVM) the application will not
150148
# exit until all thread pools have been shutdown. To prevent applications from
151-
# "hanging" on exit all thread pools include an `at_exit` handler that will
152-
# stop the thread pool when the application exits. This handler uses a brute
153-
# force method to stop the pool and makes no guarantees regarding resources being
154-
# used by any tasks still running. Registration of this `at_exit` handler can be
155-
# prevented by setting the thread pool's constructor `:auto_terminate` option to
156-
# `false` when the thread pool is created. All thread pools support this option.
149+
# "hanging" on exit, all threads can be marked as daemon according to the
150+
# `:auto_terminate` option.
157151
#
158152
# ```ruby
159-
# pool1 = Concurrent::FixedThreadPool.new(5) # an `at_exit` handler will be registered
160-
# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # prevent `at_exit` handler registration
153+
# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon
154+
# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon
161155
# ```
162156
#
163157
# @note Failure to properly shutdown a thread pool can lead to unpredictable results.
@@ -166,7 +160,7 @@ module Concurrent
166160
# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools
167161
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class
168162
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface
169-
# @see http://ruby-doc.org//core-2.2.0/Kernel.html#method-i-at_exit Kernel#at_exit
163+
# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean-
170164

171165

172166

lib/concurrent-ruby/concurrent/utility/at_exit.rb

Lines changed: 0 additions & 96 deletions
This file was deleted.

spec/concurrent/configuration_spec.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,6 @@ module Concurrent
1919
expect(Concurrent.global_io_executor).to respond_to(:post)
2020
end
2121

22-
specify 'Concurrent::AtExit.run acts on all executors with auto_terminate: true' do
23-
# The 'at_least(:once)' clauses account for global config reset
24-
expect(Concurrent.global_fast_executor).to receive(:kill).at_least(:once).with(no_args)
25-
expect(Concurrent.global_io_executor).to receive(:kill).at_least(:once).with(no_args)
26-
expect(Concurrent.global_timer_set).to receive(:kill).at_least(:once).with(no_args)
27-
Concurrent::AT_EXIT.run
28-
end
2922
end
3023
end
3124
end

spec/concurrent/executor/pool_quits.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
require 'concurrent-ruby'
66

7-
# the test relies on replicating that Minitest messed up the AtExit handling
8-
Concurrent.disable_at_exit_handlers!
97
pool = Concurrent::CachedThreadPool.new
108
pool.post do
119
sleep # sleep indefinitely

0 commit comments

Comments
 (0)