#597 server_select gets into loop when reaching NOFILE limit

Reporter Zash
Owner Zash
Created
Updated
Stars (0)  
Tags
  • Milestone-0.9
  • Status-Fixed
  • Type-Defect
  • Priority-Medium
  1. Zash on

    When reaching the NOFILE limit, the select backend gets into a loop, doing the following: 1. select() returns at least one server handler 2. it tries to call accept() on this server 3. it fails, logs an error, returns false 4. handle other things, clients etc 5. select() again (goto 1) This is with NOFILE < 1024, the code to prevent select()ing on FD# 1024 is not involved.

  2. Zash on

    Changes
    • tags Milestone-0.9
  3. Zash on

    This patch makes it pause the server for ~10s or until a client disconnects. diff -r 91e63ba02ffe net/server_select.lua --- a/net/server_select.lua Thu Jan 21 22:26:46 2016 +0100 +++ b/net/server_select.lua Thu Jan 21 22:27:30 2016 +0100 @@ -88,6 +88,7 @@ local _socketlist local _closelist local _readtimes local _writetimes +local _fullservers --// simple data types //-- @@ -130,6 +131,7 @@ local _maxsslhandshake _readtimes = { } -- key = handler, value = timestamp of last data reading _writetimes = { } -- key = handler, value = timestamp of last data writing/sending _closelist = { } -- handlers to close +_fullservers = { } -- servers in a paused state while there are too many clients _readlistlen = 0 -- length of readlist _sendlistlen = 0 -- length of sendlist @@ -219,6 +221,7 @@ wrapserver = function( listeners, socket end _readlistlen = addsocket(_readlist, socket, _readlistlen) _socketlist[ socket ] = handler + _fullservers[ handler ] = nil handler.paused = false; end end @@ -234,6 +237,7 @@ wrapserver = function( listeners, socket handler.readbuffer = function( ) if _readlistlen >= _maxselectlen or _sendlistlen >= _maxselectlen then handler.pause( ) + _fullservers[ handler ] = _currenttime out_put( "server.lua: refused new client connection: server full" ) return false end @@ -252,6 +256,8 @@ wrapserver = function( listeners, socket return; elseif err then -- maybe timeout or something else out_put( "server.lua: error with new client connection: ", tostring(err) ) + handler.pause( ) + _fullservers[ handler ] = _currenttime return false end end @@ -264,6 +270,7 @@ wrapconnection = function( server, liste out_error("server.lua: Disallowed FD number: "..socket:getfd()) -- PROTIP: Switch to libevent socket:close( ) -- Should we send some kind of error here? if server then + _fullservers[ server ] = true server.pause( ) end return nil, nil, "fd-too-large" @@ -896,6 +903,13 @@ loop = function(once) -- this is the mai next_timer_time = next_timer_time - (_currenttime - _timer); end + for server, paused_time in pairs( _fullservers ) do + if _currenttime - paused_time > 10 then + _fullservers[ server ] = nil; + server.resume(); + end + end + -- wait some time (0 by default) socket_sleep( _sleeptime ) until quitting;

    Changes
    • tags Status-Started
  4. Zash on

    Fixed in http://hg.prosody.im/trunk/rev/95e4c81291cc See also http://hg.prosody.im/trunk/rev/e8f202856fc0 http://hg.prosody.im/trunk/rev/3e1dac35af87

    Changes
    • tags Status-Fixed
    • owner Zash

New comment