Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Improve support for JRuby.

Requires JRuby 1.7.0.
  • Loading branch information...
commit e8e7f0d5972dd741f8586aab639b4559a0b9234e 1 parent 4b01abc
@FooBarWidget authored
View
90 lib/daemon_controller.rb
@@ -336,6 +336,12 @@ def running?
end
end
+ # Checks whether ping Unix domain sockets is supported. Currently
+ # this is supported on all Ruby implementations, except JRuby.
+ def self.can_ping_unix_sockets?
+ return RUBY_PLATFORM != "java"
+ end
+
private
def start_without_locking
if daemon_is_running?
@@ -579,6 +585,11 @@ def determine_lock_file(options, identifier, pid_file)
def self.fork_supported?
return RUBY_PLATFORM != "java" && RUBY_PLATFORM !~ /win32/
end
+
+ def self.spawn_supported?
+ # Process.spawn doesn't work very well in JRuby.
+ return Process.respond_to?(:spawn) && RUBY_PLATFORM != "java"
+ end
def run_command(command)
# Create tempfile for storing the command's output.
@@ -587,7 +598,7 @@ def run_command(command)
File.chmod(0666, tempfile_path)
tempfile.close
- if self.class.fork_supported? || Process.respond_to?(:spawn)
+ if self.class.fork_supported? || self.class.spawn_supported?
if Process.respond_to?(:spawn)
options = {
:in => "/dev/null",
@@ -687,19 +698,74 @@ def run_ping_command
end
elsif @ping_command.is_a?(Array)
type, *args = @ping_command
-
- case type
- when :tcp
- socket_domain = Socket::Constants::AF_INET
- hostname, port = args
- sockaddr = Socket.pack_sockaddr_in(port, hostname)
- when :unix
- socket_domain = Socket::Constants::AF_LOCAL
- sockaddr = Socket.pack_sockaddr_un(args[0])
+ if self.class.can_ping_unix_sockets?
+ case type
+ when :tcp
+ socket_domain = Socket::Constants::AF_INET
+ hostname, port = args
+ sockaddr = Socket.pack_sockaddr_in(port, hostname)
+ when :unix
+ socket_domain = Socket::Constants::AF_LOCAL
+ sockaddr = Socket.pack_sockaddr_un(args[0])
+ else
+ raise ArgumentError, "Unknown ping command type #{type.inspect}"
+ end
+ return ping_socket(socket_domain, sockaddr)
else
- raise ArgumentError, "Unknown ping command type #{type.inspect}"
+ case type
+ when :tcp
+ hostname, port = args
+ return ping_socket(hostname, port)
+ when :unix
+ raise "Pinging Unix domain sockets is not supported on this Ruby implementation"
+ else
+ raise ArgumentError, "Unknown ping command type #{type.inspect}"
+ end
end
+ else
+ return system(@ping_command)
+ end
+ end
+
+ if !can_ping_unix_sockets?
+ require 'java'
+
+ def ping_socket(host_name, port)
+ channel = java.nio.channels.SocketChannel.open
+ begin
+ address = java.net.InetSocketAddress.new(host_name, port)
+ channel.configure_blocking(false)
+ if channel.connect(address)
+ return true
+ end
+ deadline = Time.now.to_f + 0.1
+ done = false
+ while true
+ begin
+ if channel.finish_connect
+ return true
+ end
+ rescue java.net.ConnectException => e
+ if e.message =~ /Connection refused/i
+ return false
+ else
+ throw e
+ end
+ end
+
+ # Not done connecting and no error.
+ sleep 0.01
+ if Time.now.to_f >= deadline
+ return false
+ end
+ end
+ ensure
+ channel.close
+ end
+ end
+ else
+ def ping_socket(socket_domain, sockaddr)
begin
socket = Socket.new(socket_domain, Socket::Constants::SOCK_STREAM, 0)
begin
@@ -720,8 +786,6 @@ def run_ping_command
ensure
socket.close if socket
end
- else
- return system(@ping_command)
end
end
View
4 lib/daemon_controller/lock_file.rb
@@ -78,7 +78,7 @@ def exclusive_lock
# The lock file *must* be writable, otherwise an Errno::EACCESS
# exception will be raised.
def shared_lock
- File.open(@filename, 'w') do |f|
+ File.open(@filename, 'w+') do |f|
if Fcntl.const_defined? :F_SETFD
f.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
end
@@ -93,7 +93,7 @@ def shared_lock
#
# If a lock can be obtained, then the given block will be yielded.
def try_shared_lock
- File.open(@filename, 'w') do |f|
+ File.open(@filename, 'w+') do |f|
if Fcntl.const_defined? :F_SETFD
f.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
end
View
27 spec/daemon_controller_spec.rb
@@ -128,7 +128,7 @@
end
end
- if DaemonController.send(:fork_supported?) || Process.respond_to?(:spawn)
+ if DaemonController.send(:fork_supported?) || DaemonController.send(:spawn_supported?)
it "kills the daemon if it doesn't start in time and hasn't forked " <<
"yet, on platforms where Ruby supports fork() or Process.spawn" do
begin
@@ -209,7 +209,7 @@
log.should == ["before_start", "start_command"]
end
- if DaemonController.send(:fork_supported?) || Process.respond_to?(:spawn)
+ if DaemonController.send(:fork_supported?) || DaemonController.send(:spawn_supported?)
it "keeps the file descriptors in 'keep_ios' open" do
a, b = IO.pipe
begin
@@ -398,18 +398,27 @@
end
specify "the ping command may be [:tcp, hostname, port]" do
- new_controller(:ping_command => [:tcp, "localhost", 8278])
+ new_controller(:ping_command => [:tcp, "127.0.0.1", 8278])
@controller.send(:run_ping_command).should be_false
- @server = TCPServer.new('localhost', 8278)
+ @server = TCPServer.new('127.0.0.1', 8278)
@controller.send(:run_ping_command).should be_true
end
- specify "the ping command may be [:unix, filename]" do
- new_controller(:ping_command => [:unix, "spec/foo.sock"])
- @controller.send(:run_ping_command).should be_false
+ if DaemonController.can_ping_unix_sockets?
+ specify "the ping command may be [:unix, filename]" do
+ new_controller(:ping_command => [:unix, "spec/foo.sock"])
+ @controller.send(:run_ping_command).should be_false
- @server = UNIXServer.new('spec/foo.sock')
- @controller.send(:run_ping_command).should be_true
+ @server = UNIXServer.new('spec/foo.sock')
+ @controller.send(:run_ping_command).should be_true
+ end
+ else
+ specify "a ping command of type [:unix, filename] is not supported on this Ruby implementation" do
+ new_controller(:ping_command => [:unix, "spec/foo.sock"])
+ @server = UNIXServer.new('spec/foo.sock')
+ lambda { @controller.send(:run_ping_command) }.should raise_error(
+ "Pinging Unix domain sockets is not supported on this Ruby implementation")
+ end
end
end
View
5 spec/echo_server.rb
@@ -1,5 +1,8 @@
-#!/usr/bin/env ruby
+#!/usr/bin/ruby
# A simple echo server, used by the unit test.
+# The hashbang is explicitly set to /usr/bin/ruby because we need
+# a Ruby implementation that starts fast and supports forking. The
+# Ruby in $PATH may be JRuby which is neither.
require 'socket'
require 'optparse'
Please sign in to comment.
Something went wrong with that request. Please try again.