Skip to content

Commit 7100ae4

Browse files
ayufanjonleighton
authored andcommitted
Configure threads to not abort on exceptions (#484)
* 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
1 parent f07711b commit 7100ae4

File tree

7 files changed

+25
-5
lines changed

7 files changed

+25
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.7.2
2+
3+
* Use `Spring.failsafe_thread` to prevent threads from aborting process due to `Thread.abort_on_exception` when set to `true`
4+
15
## 1.7.1
26

37
* Specify absolute path to spring binfile when starting the server

lib/spring/application.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ def wait(pid, streams, client)
306306
@mutex.synchronize { @waiting << pid }
307307

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

323-
Thread.new {
323+
Spring.failsafe_thread {
324324
while signal = client.gets.chomp
325325
begin
326326
Process.kill(signal, -Process.getpgid(pid))

lib/spring/application_manager.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def start_child(preload = false)
116116
def start_wait_thread(pid, child)
117117
Process.detach(pid)
118118

119-
Thread.new {
119+
Spring.failsafe_thread {
120120
# The recv can raise an ECONNRESET, killing the thread, but that's ok
121121
# as if it does we're no longer interested in the child
122122
loop do

lib/spring/boot.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@
66
require "spring/process_title_updater"
77
require "spring/json"
88
require "spring/watcher"
9+
require "spring/failsafe_thread"
10+

lib/spring/failsafe_thread.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
require 'thread'
2+
3+
module Spring
4+
class << self
5+
def failsafe_thread
6+
Thread.new {
7+
begin
8+
yield
9+
rescue
10+
end
11+
}
12+
end
13+
end
14+
end

lib/spring/process_title_updater.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ProcessTitleUpdater
1010
def self.run(&block)
1111
updater = new(&block)
1212

13-
Thread.new {
13+
Spring.failsafe_thread {
1414
$0 = updater.value
1515
loop { $0 = updater.next }
1616
}

lib/spring/server.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def shutdown
106106
end
107107
end
108108

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

112112
def write_pidfile

0 commit comments

Comments
 (0)