Skip to content

Commit

Permalink
Configure threads to not abort on exceptions (#484)
Browse files Browse the repository at this point in the history
* Configure all threads to not abort on exceptions

This solves long outstanding issue: #396.
This happens, because some applications or gems do overwrite global setting of `Thread.abort_on_exception=` which is by default set to `false`.
This leads to application process to exit and making the spring unable to recover from that.

* Use rescue blocks instead of `abort_on_exception=`

* Rescue PTY

* Use `Spring.failsafe_thread`

* Add CHANGELOG
  • Loading branch information
ayufan authored and jonleighton committed Jul 1, 2016
1 parent f07711b commit 7100ae4
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.7.2

* Use `Spring.failsafe_thread` to prevent threads from aborting process due to `Thread.abort_on_exception` when set to `true`

## 1.7.1

* Specify absolute path to spring binfile when starting the server
Expand Down
4 changes: 2 additions & 2 deletions lib/spring/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ def wait(pid, streams, client)
@mutex.synchronize { @waiting << pid }

# Wait in a separate thread so we can run multiple commands at once
Thread.new {
Spring.failsafe_thread {
begin
_, status = Process.wait2 pid
log "#{pid} exited with #{status.exitstatus}"
Expand All @@ -320,7 +320,7 @@ def wait(pid, streams, client)
end
}

Thread.new {
Spring.failsafe_thread {
while signal = client.gets.chomp
begin
Process.kill(signal, -Process.getpgid(pid))
Expand Down
2 changes: 1 addition & 1 deletion lib/spring/application_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def start_child(preload = false)
def start_wait_thread(pid, child)
Process.detach(pid)

Thread.new {
Spring.failsafe_thread {
# The recv can raise an ECONNRESET, killing the thread, but that's ok
# as if it does we're no longer interested in the child
loop do
Expand Down
2 changes: 2 additions & 0 deletions lib/spring/boot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
require "spring/process_title_updater"
require "spring/json"
require "spring/watcher"
require "spring/failsafe_thread"

14 changes: 14 additions & 0 deletions lib/spring/failsafe_thread.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'thread'

module Spring
class << self
def failsafe_thread
Thread.new {
begin
yield
rescue
end
}
end
end
end
2 changes: 1 addition & 1 deletion lib/spring/process_title_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ProcessTitleUpdater
def self.run(&block)
updater = new(&block)

Thread.new {
Spring.failsafe_thread {
$0 = updater.value
loop { $0 = updater.next }
}
Expand Down
2 changes: 1 addition & 1 deletion lib/spring/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def shutdown
end
end

@applications.values.map { |a| Thread.new { a.stop } }.map(&:join)
@applications.values.map { |a| Spring.failsafe_thread { a.stop } }.map(&:join)
end

def write_pidfile
Expand Down

0 comments on commit 7100ae4

Please sign in to comment.