Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Setup locking around Process.kill process

This fixes a potential race that could occur in this subprocess. The
problem is that when two signals were received at the same time, there
was a race condition.

What could happen is that when two signals were received, it would run
the signal handler twice. One handler could set signaled to true, the
other one would see signaled as false and exit before the other handler
would print the "signaled" string.

With a Mutex we can use try_lock to attempt to lock once and then exit.
This makes sure we only print "signaled" once and immediately exit.

Why not use Mutex.synchronize {} one might ask here. Well, that doesn't
work since signals are handled in the same thread, so what happens then
is that you can recursive locking errors since the Mutex is locked twice
in the same thread so the deadlock detection kicks in and causes an
exception.
  • Loading branch information...
commit 571873850cfb23fc3ec1fdebe8d8678602c4f4d0 1 parent cb13394
@dbussink dbussink authored
Showing with 5 additions and 6 deletions.
  1. +5 −6 spec/ruby/core/process/fixtures/kill.rb
View
11 spec/ruby/core/process/fixtures/kill.rb
@@ -1,3 +1,5 @@
+require 'thread'
+
pid_file = ARGV.shift
scenario = ARGV.shift
ruby_exe = ARGV.shift
@@ -7,16 +9,13 @@
# instead, which will likely abort the specs process.
Process.setsid if scenario
-signaled = false
+mutex = Mutex.new
Signal.trap(:TERM) do
- unless signaled
- signaled = true
-
+ if mutex.try_lock
puts "signaled"
+ Process.exit!
end
-
- exit
end
File.open(pid_file, "wb") { |f| f.puts Process.pid }
Please sign in to comment.
Something went wrong with that request. Please try again.