[前][次][番号順一覧][スレッド一覧]

ruby-changes:35596

From: akr <ko1@a...>
Date: Mon, 22 Sep 2014 02:06:12 +0900 (JST)
Subject: [ruby-changes:35596] akr:r47678 (trunk): * lib/drb/drb.rb: Support graceful shutdown.

akr	2014-09-22 02:06:05 +0900 (Mon, 22 Sep 2014)

  New Revision: 47678

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47678

  Log:
    * lib/drb/drb.rb: Support graceful shutdown.
      (DRbTCPSocket#initialize): Create a pipe for shutdown notification.
      (DRbTCPSocket#close): Invoke close_shutdown_pipe.
      (DRbTCPSocket#close_shutdown_pipe): New private method.
      (DRbTCPSocket#accept): Use accept_or_shutdown.
      (DRbTCPSocket#accept_or_shutdown): New private method which returns
      nil on shutdown.
      (DRbServer#stop_service): Use shutdown instead of Thread#kill.
      (DRbServer#run): Break infinite loop when main_loop returns nil.
      (DRbServer#main_loop): @protocol.accept may return nil.
    
    * lib/drb/ssl.rb: Follow above change.
    
    * lib/drb/unix.rb: Ditto.

  Modified files:
    trunk/ChangeLog
    trunk/lib/drb/drb.rb
    trunk/lib/drb/ssl.rb
    trunk/lib/drb/unix.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 47677)
+++ ChangeLog	(revision 47678)
@@ -1,3 +1,20 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Sep 22 02:04:25 2014  Tanaka Akira  <akr@f...>
+
+	* lib/drb/drb.rb: Support graceful shutdown.
+	  (DRbTCPSocket#initialize): Create a pipe for shutdown notification.
+	  (DRbTCPSocket#close): Invoke close_shutdown_pipe.
+	  (DRbTCPSocket#close_shutdown_pipe): New private method.
+	  (DRbTCPSocket#accept): Use accept_or_shutdown.
+	  (DRbTCPSocket#accept_or_shutdown): New private method which returns
+	  nil on shutdown.
+	  (DRbServer#stop_service): Use shutdown instead of Thread#kill.
+	  (DRbServer#run): Break infinite loop when main_loop returns nil.
+	  (DRbServer#main_loop): @protocol.accept may return nil.
+
+	* lib/drb/ssl.rb: Follow above change.
+
+	* lib/drb/unix.rb: Ditto.
+
 Sun Sep 21 13:54:36 2014  Masaki Matsushita <glass.saga@g...>
 
 	* time.c: raise exception when minutes of utc_offset is out of 00-59.
Index: lib/drb/ssl.rb
===================================================================
--- lib/drb/ssl.rb	(revision 47677)
+++ lib/drb/ssl.rb	(revision 47678)
@@ -322,7 +322,8 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/ssl.rb#L322
     def accept # :nodoc:
       begin
       while true
-        soc = @socket.accept
+        soc = accept_or_shutdown
+        return nil unless soc
         break if (@acl ? @acl.allow_socket?(soc) : true)
         soc.close
       end
Index: lib/drb/unix.rb
===================================================================
--- lib/drb/unix.rb	(revision 47677)
+++ lib/drb/unix.rb	(revision 47678)
@@ -98,10 +98,12 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/unix.rb#L98
       @socket.close
       File.unlink(path) if @server_mode
       @socket = nil
+      close_shutdown_pipe
     end
 
     def accept
-      s = @socket.accept
+      s = accept_or_shutdown
+      return nil unless s
       self.class.new(nil, s, @config)
     end
 
Index: lib/drb/drb.rb
===================================================================
--- lib/drb/drb.rb	(revision 47677)
+++ lib/drb/drb.rb	(revision 47678)
@@ -905,6 +905,7 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L905
       @acl = config[:tcp_acl]
       @msg = DRbMessage.new(config)
       set_sockopt(@socket)
+      @shutdown_pipe_r, @shutdown_pipe_w = IO.pipe
     end
 
     # Get the URI that we are connected to.
@@ -952,14 +953,28 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L953
         @socket.close
         @socket = nil
       end
+      close_shutdown_pipe
     end
 
+    def close_shutdown_pipe
+      if @shutdown_pipe_r && !@shutdown_pipe_r.closed?
+        @shutdown_pipe_r.close
+        @shutdown_pipe_r = nil
+      end
+      if @shutdown_pipe_w && !@shutdown_pipe_w.closed?
+        @shutdown_pipe_w.close
+        @shutdown_pipe_w = nil
+      end
+    end
+    private :close_shutdown_pipe
+
     # On the server side, for an instance returned by #open_server,
     # accept a client connection and return a new instance to handle
     # the server's side of this client-server session.
     def accept
       while true
-        s = @socket.accept
+        s = accept_or_shutdown
+        return nil unless s
         break if (@acl ? @acl.allow_socket?(s) : true)
         s.close
       end
@@ -971,6 +986,20 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L986
       self.class.new(uri, s, @config)
     end
 
+    def accept_or_shutdown
+      readables, = IO.select([@socket, @shutdown_pipe_r])
+      if readables.include? @shutdown_pipe_r
+        return nil
+      end
+      @socket.accept
+    end
+    private :accept_or_shutdown
+
+    # Graceful shutdown
+    def shutdown
+      @shutdown_pipe_w.close if @shutdown_pipe_w && !@shutdown_pipe_w.closed?
+    end
+
     # Check to see if this connection is alive.
     def alive?
       return false unless @socket
@@ -1438,7 +1467,12 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1467
       if  Thread.current['DRb'] && Thread.current['DRb']['server'] == self
         Thread.current['DRb']['stop_service'] = true
       else
-        @thread.kill.join
+        if @protocol.respond_to? :shutdown
+          @protocol.shutdown
+        else
+          @thread.kill # xxx: Thread#kill
+        end
+        @thread.join
       end
     end
 
@@ -1463,8 +1497,7 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1497
     def run
       Thread.start do
         begin
-          while true
-            main_loop
+          while main_loop
           end
         ensure
           @protocol.close if @protocol
@@ -1607,7 +1640,9 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/drb.rb#L1640
     # returning responses, until the client closes the connection
     # or a local method call fails.
     def main_loop
-      Thread.start(@protocol.accept) do |client|
+      client0 = @protocol.accept
+      return nil if !client0
+      Thread.start(client0) do |client|
         @grp.add Thread.current
         Thread.current['DRb'] = { 'client' => client ,
                                   'server' => self }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]