Project

General

Profile

Actions

Bug #6369

closed

GServer blocking after shutdown called

Added by stevegoobermanhill (stephen gooberman-hill) over 12 years ago. Updated almost 7 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 1.9.2p290 (2011-07-09 revision 32553) [i686-linux]
[ruby-core:44666]

Description

Hi,
My investigation of bug #6358 points the finger at GServer triggering bug #5343 on lower power arm-linux platforms, because of the blocking TCPServer#accept call.

I believe there is also an underlying design flaw: the main thread (@tcpServerThread) is blocked in the TCPServer#accept call, so if no further connections are attempted after #shutdown() is called, the main thread remains blocked and will hang until it is forced into the ensure clause by the destruction of the GServer object by GC

This proposed patch to GServer seems to tackle the first issue, and also effectively makes the TCPServer#accept nonblocking by using a Timeout block to ensure that the main thread periodically (every 0.1s) has the chance to shut down gracefully if no further connections are forthcoming.

It also adds a GServer#shutdown! method which will block until the GServer has gracefully shut down

59,60c59,62
< # server.shutdown
< #

server.shutdown #will not wait for the server thread to quit

server.shutdown! #blocks until server thread has quit

122c124,131
<

def shutdown!
shutdown
while !stopped?
sleep 0.01
end
end

189c198
< @@servicesMutex.synchronize {

@@servicesMutex.synchronize do

197,198c206,208
< }
< @tcpServerThread = Thread.new {

end

@tcpServerThread = Thread.new do

202c212
< @connectionsMutex.synchronize {

      @connectionsMutex.synchronize do

206,217c216,240
< }
< client = @tcpServer.accept
< @connections << Thread.new(client) { |myClient|
< begin
< myPort = myClient.peeraddr[1]
< serve(myClient) if @audit or connecting(myClient)
< rescue => detail
< error(detail) if @debug
< ensure
< begin
< myClient.close
< rescue

      end
      
      
      begin
        Timeout::timeout(0.1) do 
          client = @tcpServer.accept
     
          @connections << Thread.new(client) do |myClient|
            begin
              myPort = myClient.peeraddr[1]
              serve(myClient) if !@audit or connecting(myClient)
            rescue => detail
              error(detail) if @debug
            ensure
              begin
                myClient.close
                sleep 1
              rescue
              end
              @connectionsMutex.synchronize do
                @connections.delete(Thread.current)
                @connectionsCV.signal
              end
              disconnecting(myPort) if @audit
            end

219,223d241
< @connectionsMutex.synchronize {
< @connections.delete(Thread.current)
< @connectionsCV.signal
< }
< disconnecting(myPort) if @audit
225c243,245
< }

     rescue Timeout::Error
     end

226a247

235c256
< @connectionsMutex.synchronize {

      @connectionsMutex.synchronize do

239c260
< }

      end

244c265
< @@servicesMutex.synchronize {

    @@servicesMutex.synchronize do

246c267
< }

    end

249c270
< }

end
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0