Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add builtin support for pinging sockets.

  • Loading branch information...
commit a88c8fdb9fff8cb5243da68a4b3abdd9cdb5957a 1 parent c1d2ec4
@FooBarWidget authored
View
7 README.markdown
@@ -31,10 +31,9 @@ It provides the following functionality:
## Resources
-* [Website](http://github.com/FooBarWidget/daemon_controller)
+* [Website](https://github.com/FooBarWidget/daemon_controller)
* [RDoc](http://rdoc.info/projects/FooBarWidget/daemon_controller)
* [Git repository](git://github.com/FooBarWidget/daemon_controller.git)
-* [RubyForge project](http://rubyforge.org/projects/daemoncontrol/)
What is it for?
@@ -317,7 +316,7 @@ That can be done with the following code:
controller = DaemonController.new(
:identifier => 'Apache web server',
:start_command => 'apachectl -f apache.conf -k start',
- :ping_command => lambda { TCPSocket.new('localhost', 1234) },
+ :ping_command => [:tcp, 'localhost', 1234],
:pid_file => 'apache.pid',
:log_file => 'apache.log',
:start_timeout => 25
@@ -401,7 +400,7 @@ This can be achieved with the following code:
:identifier => 'Sphinx search server',
:start_command => "searchd -c config/sphinx.conf",
:before_start => method(:before_start),
- :ping_command => lambda { TCPSocket.new('localhost', SEARCH_SERVER_PORT) },
+ :ping_command => [:tcp, 'localhost', SEARCH_SERVER_PORT],
:pid_file => 'tmp/pids/sphinx.pid',
:log_file => 'log/sphinx.log')
end
View
42 lib/daemon_controller.rb
@@ -85,6 +85,11 @@ class DaemonizationTimeout < TimeoutError
# The value may be a command string. This command must exit with an exit code of
# 0 if the daemon can be successfully connected to, or exit with a non-0 exit
# code on failure.
+ #
+ # The value may also be an Array which specifies the socket address of the daemon.
+ # It must be in one of the following forms:
+ # - [:tcp, host_name, port]
+ # - [:unix, filename]
#
# The value may also be a Proc, which returns an expression that evaluates to
# true (indicating that the daemon can be connected to) or false (failure).
@@ -658,11 +663,46 @@ def run_ping_command
rescue *ALLOWED_CONNECT_EXCEPTIONS
return false
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])
+ else
+ raise ArgumentError, "Unknown ping command type #{type.inspect}"
+ end
+
+ begin
+ socket = Socket.new(socket_domain, Socket::Constants::SOCK_STREAM, 0)
+ begin
+ socket.connect_nonblock(sockaddr)
+ rescue Errno::ENOENT, Errno::EINPROGRESS, Errno::EAGAIN, Errno::EWOULDBLOCK
+ if select(nil, [socket], nil, 0.1)
+ begin
+ socket.connect_nonblock(sockaddr)
+ rescue Errno::EISCONN
+ end
+ else
+ raise Errno::ECONNREFUSED
+ end
+ end
+ return true
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
+ return false
+ ensure
+ socket.close if socket
+ end
else
return system(@ping_command)
end
end
-
+
def safe_fork(double_fork)
pid = fork
if pid.nil?
View
2  lib/daemon_controller/spawn.rb
@@ -19,6 +19,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
-# Used on Ruby 1.9 because forking is not safe.
+# Used on Ruby 1.9 because forking may not be safe/supported on all platforms.
Process.setsid
Process.spawn(ARGV[0])
View
24 spec/daemon_controller_spec.rb
@@ -361,4 +361,28 @@
server.close
end
end
+
+ specify "the ping command may be [:tcp, hostname, port]" do
+ new_controller(:ping_command => [:tcp, "localhost", 8278])
+ @controller.send(:run_ping_command).should be_false
+
+ server = TCPServer.new('localhost', 8278)
+ begin
+ @controller.send(:run_ping_command).should be_true
+ ensure
+ server.close
+ end
+ 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
+
+ server = UNIXServer.new('spec/foo.sock')
+ begin
+ @controller.send(:run_ping_command).should be_true
+ ensure
+ server.close
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.