From 715f8084eb2f9b3f58f72664ddd6deaacd1e24bf Mon Sep 17 00:00:00 2001 From: gonubana Date: Tue, 21 Mar 2023 14:18:06 +0200 Subject: [PATCH] Prevent a race condition where the number of connected clients could overtake the set maximum number of concurrent connections. Fixes #1 --- lib/gserver.rb | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/gserver.rb b/lib/gserver.rb index 78593ee..dab52cb 100644 --- a/lib/gserver.rb +++ b/lib/gserver.rb @@ -158,7 +158,7 @@ def join # # +client+:: a TCPSocket instance representing the client that connected # - # Return true to allow this client to connect, false to prevent it. + # Return true to allow this client to be served, false to prevent it. def connecting(client) addr = client.peeraddr log("#{self.class} #{@host}:#{@port} client:#{addr[1]} " + @@ -167,9 +167,9 @@ def connecting(client) end - # Called when a client disconnects, if audition is enabled. + # Called when a client disconnects, if auditing is enabled. # - # +clientPort+:: the port of the client that is connecting + # +clientPort+:: the port of the client that is disconnecting def disconnecting(clientPort) log("#{self.class} #{@host}:#{@port} " + "client:#{clientPort} disconnect") @@ -242,7 +242,7 @@ def start(maxConnections = -1) raise "server is already running" if !stopped? @shutdown = false @maxConnections = maxConnections if maxConnections > 0 - @@servicesMutex.synchronize { + @@servicesMutex.synchronize { if GServer.in_service?(@port,@host) raise "Port already in use: #{host}:#{@port}!" end @@ -255,14 +255,16 @@ def start(maxConnections = -1) begin starting if @audit while !@shutdown - @connectionsMutex.synchronize { - while @connections.size >= @maxConnections - @connectionsCV.wait(@connectionsMutex) - end + connection = [] + @connectionsMutex.synchronize { + while @connections.size >= @maxConnections + @connectionsCV.wait(@connectionsMutex) + end + @connections << connection } client = @tcpServer.accept - Thread.new(client) { |myClient| - @connections << Thread.current + Thread.new(client, connection) { |myClient, myConnection| + myConnection << Thread.current begin myPort = myClient.peeraddr[1] serve(myClient) if !@audit or connecting(myClient) @@ -274,7 +276,7 @@ def start(maxConnections = -1) rescue end @connectionsMutex.synchronize { - @connections.delete(Thread.current) + @connections.delete(myConnection) @connectionsCV.signal } disconnecting(myPort) if @audit @@ -289,13 +291,13 @@ def start(maxConnections = -1) rescue end if @shutdown - @connectionsMutex.synchronize { - while @connections.size > 0 - @connectionsCV.wait(@connectionsMutex) - end + @connectionsMutex.synchronize { + while @connections.size > 0 + @connectionsCV.wait(@connectionsMutex) + end } else - @connections.each { |c| c.raise "stop" } + @connections.each { |(c)| c&.raise "stop" } end @tcpServerThread = nil @@servicesMutex.synchronize {