Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add support for JRuby and Rubinius.

As a consequence, Ruby processes now respond to SIGABRT in the same way
as SIGHUP because the JVM does not allow hooking into SIGHUP.
  • Loading branch information...
commit 0630abcb0ae24668dab6ffecda459fc2b381582d 1 parent 9048f95
Hongli Lai authored October 26, 2012
86  lib/phusion_passenger/request_handler.rb
@@ -123,26 +123,22 @@ def initialize(owner_pipe, options = {})
123 123
 		#############
124 124
 
125 125
 		@server_sockets = {}
  126
+		
126 127
 		if should_use_unix_sockets?
127 128
 			@main_socket_address, @main_socket = create_unix_socket_on_filesystem
128  
-			@server_sockets[:main] = {
129  
-				:address     => "unix:#{@main_socket_address}",
130  
-				:socket      => @main_socket,
131  
-				:protocol    => :session,
132  
-				:concurrency => @concurrency
133  
-			}
134 129
 		else
135 130
 			@main_socket_address, @main_socket = create_tcp_socket
136  
-			@server_sockets[:main] = {
137  
-				:addres      => "tcp://#{@main_socket_address}",
138  
-				:socket      => @main_socket,
139  
-				:protocol    => :session,
140  
-				:concurrency => @concurrency
141  
-			}
142 131
 		end
  132
+		@server_sockets[:main] = {
  133
+			:address     => @main_socket_address,
  134
+			:socket      => @main_socket,
  135
+			:protocol    => :session,
  136
+			:concurrency => @concurrency
  137
+		}
  138
+
143 139
 		@http_socket_address, @http_socket = create_tcp_socket
144 140
 		@server_sockets[:http] = {
145  
-			:address     => "tcp://#{@http_socket_address}",
  141
+			:address     => @http_socket_address,
146 142
 			:socket      => @http_socket,
147 143
 			:protocol    => :http,
148 144
 			:concurrency => 1
@@ -315,15 +311,21 @@ def should_use_unix_sockets?
315 311
 		# with this fake-EOF bug once in a while, but not nearly as often
316 312
 		# as with Unix sockets.
317 313
 		#
318  
-		# This problem no longer applies today. The client socket is now
319  
-		# created directly in the web server, and the bug is no longer
  314
+		# This problem no longer applies today. The web server now passes
  315
+		# all I/O through the HelperAgent, and the bug is no longer
320 316
 		# triggered. Nevertheless, we keep this function intact so that
321 317
 		# if something like this ever happens again, we know why, and we
322 318
 		# can easily reactivate the workaround. Or maybe if we just need
323 319
 		# TCP sockets for some other reason.
324 320
 		
325 321
 		#return RUBY_PLATFORM !~ /darwin/
326  
-		return true
  322
+
  323
+		ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
  324
+		# Unix domain socket implementation on JRuby
  325
+		# is still bugged as of version 1.7.0. They can
  326
+		# cause unexplicable freezes when used in combination
  327
+		# with threading.
  328
+		return ruby_engine != "jruby"
327 329
 	end
328 330
 
329 331
 	def create_unix_socket_on_filesystem
@@ -340,7 +342,7 @@ def create_unix_socket_on_filesystem
340 342
 				socket.listen(BACKLOG_SIZE)
341 343
 				socket.close_on_exec!
342 344
 				File.chmod(0600, socket_address)
343  
-				return [socket_address, socket]
  345
+				return ["unix:#{socket_address}", socket]
344 346
 			rescue Errno::EADDRINUSE
345 347
 				# Do nothing, try again with another name.
346 348
 			end
@@ -353,7 +355,7 @@ def create_tcp_socket
353 355
 		socket = TCPServer.new('127.0.0.1', 0)
354 356
 		socket.listen(BACKLOG_SIZE)
355 357
 		socket.close_on_exec!
356  
-		socket_address = "127.0.0.1:#{socket.addr[1]}"
  358
+		socket_address = "tcp://127.0.0.1:#{socket.addr[1]}"
357 359
 		return [socket_address, socket]
358 360
 	end
359 361
 
@@ -387,12 +389,10 @@ def install_useful_signal_handlers
387 389
 		end if trappable_signals.has_key?(SOFT_TERMINATION_SIGNAL.sub(/^SIG/, ''))
388 390
 		
389 391
 		trap('ABRT') do
390  
-			raise SignalException, "SIGABRT"
  392
+			print_status_report
391 393
 		end if trappable_signals.has_key?('ABRT')
392  
-		
393 394
 		trap('QUIT') do
394  
-			warn(global_backtrace_report)
395  
-			warn("Threads: #{@threads.inspect}")
  395
+			print_status_report
396 396
 		end if trappable_signals.has_key?('QUIT')
397 397
 	end
398 398
 	
@@ -402,6 +402,11 @@ def revert_signal_handlers
402 402
 		end
403 403
 	end
404 404
 
  405
+	def print_status_report
  406
+		warn(Utils.global_backtrace_report)
  407
+		warn("Threads: #{@threads.inspect}")
  408
+	end
  409
+
405 410
 	def start_threads
406 411
 		main_socket_options = {
407 412
 			:app => @app,
@@ -459,11 +464,40 @@ def unregister_current_thread
459 464
 	end
460 465
 
461 466
 	def wait_until_termination
462  
-		ios = select([@owner_pipe, @graceful_termination_pipe[0]])[0]
463  
-		if ios.include?(@owner_pipe)
464  
-			trace(2, "Owner pipe closed")
  467
+		ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
  468
+		if ruby_engine == "jruby"
  469
+			# On JRuby, selecting on an input TTY always returns, so
  470
+			# we use threads to do the job.
  471
+			owner_pipe_watcher = IO.pipe
  472
+			owner_pipe_watcher_thread = Thread.new do
  473
+				Thread.current.abort_on_exception = true
  474
+				Thread.current[:name] = "Owner pipe waiter"
  475
+				begin
  476
+					@owner_pipe.read(1)
  477
+				ensure
  478
+					owner_pipe_watcher[1].write('x')
  479
+				end
  480
+			end
  481
+			begin
  482
+				ios = select([owner_pipe_watcher[0], @graceful_termination_pipe[0]])[0]
  483
+				if ios.include?(owner_pipe_watcher[0])
  484
+					trace(2, "Owner pipe closed")
  485
+				else
  486
+					trace(2, "Graceful termination pipe closed")
  487
+				end
  488
+			ensure
  489
+				owner_pipe_watcher_thread.kill
  490
+				owner_pipe_watcher_thread.join
  491
+				owner_pipe_watcher[0].close if !owner_pipe_watcher[0].closed?
  492
+				owner_pipe_watcher[1].close if !owner_pipe_watcher[1].closed?
  493
+			end
465 494
 		else
466  
-			trace(2, "Graceful termination pipe closed")
  495
+			ios = select([@owner_pipe, @graceful_termination_pipe[0]])[0]
  496
+			if ios.include?(@owner_pipe)
  497
+				trace(2, "Owner pipe closed")
  498
+			else
  499
+				trace(2, "Graceful termination pipe closed")
  500
+			end
467 501
 		end
468 502
 	end
469 503
 
8  lib/phusion_passenger/ruby_core_enhancements.rb
@@ -131,10 +131,6 @@ module Signal
131 131
 	def self.list_trappable
132 132
 		ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
133 133
 		case ruby_engine
134  
-		when "ruby"
135  
-			result = Signal.list
136  
-			result.delete("ALRM")
137  
-			result.delete("VTALRM")
138 134
 		when "jruby"
139 135
 			result = Signal.list
140 136
 			result.delete("QUIT")
@@ -143,8 +139,12 @@ def self.list_trappable
143 139
 			result.delete("KILL")
144 140
 			result.delete("SEGV")
145 141
 			result.delete("USR1")
  142
+			result.delete("IOT")
  143
+			result.delete("EXIT")
146 144
 		else
147 145
 			result = Signal.list
  146
+			result.delete("ALRM")
  147
+			result.delete("VTALRM")
148 148
 		end
149 149
 		
150 150
 		# Don't touch SIGCHLD no matter what! On OS X waitpid() will

0 notes on commit 0630abc

Please sign in to comment.
Something went wrong with that request. Please try again.