Skip to content

Commit

Permalink
Fix for nim-lang#18161 Too many open files.
Browse files Browse the repository at this point in the history
I've been checking the code in asynchttpserver file and found that in the processClient function the connection is never closed after the "while" loop. So even if the keepalive header is off the number of open files is always increasing. With the keepalive off and if the connection is closed after the "while" loop the server never dies.

If the header keepalive is on and if it exceeds the pre-defined number of file descriptors it automatically closes the connection! I also added a timeout for keepalive connections.
  • Loading branch information
mrhdias authored Jun 6, 2021
1 parent 44e653a commit 3803d5c
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/pure/asynchttpserver.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

import asyncnet, asyncdispatch, parseutils, uri, strutils
import httpcore
from times import DateTime, now, `-`, inSeconds

export httpcore except parseHeader

Expand Down Expand Up @@ -289,6 +290,9 @@ proc processRequest(
request.client.close()
return false

const
keepaliveTimeout* {.intdefine.} = 60 ### default value for keepaliveTimeout in seconds

proc processClient(server: AsyncHttpServer, client: AsyncSocket, address: string,
callback: proc (request: Request):
Future[void] {.closure, gcsafe.}) {.async.} =
Expand All @@ -298,12 +302,20 @@ proc processClient(server: AsyncHttpServer, client: AsyncSocket, address: string
var lineFut = newFutureVar[string]("asynchttpserver.processClient")
lineFut.mget() = newStringOfCap(80)

let startTimeout = now()
while not client.isClosed:
let fds = activeDescriptors()
# The maxFDs should be replaced by the keepaliveConn?
if (fds > server.maxFDs) or ((now() - startTimeout).inSeconds > keepaliveTimeout):
break # Connection timeout

let retry = await processRequest(
server, request, client, address, lineFut, callback
)
if not retry: break

client.close() # Close the connection to not increase the number of open files.

const
nimMaxDescriptorsFallback* {.intdefine.} = 16_000 ## fallback value for \
## when `maxDescriptors` is not available.
Expand Down Expand Up @@ -339,6 +351,7 @@ proc acceptRequest*(server: AsyncHttpServer,
var (address, client) = await server.socket.acceptAddr()
asyncCheck processClient(server, client, address, callback)


proc serve*(server: AsyncHttpServer, port: Port,
callback: proc (request: Request): Future[void] {.closure, gcsafe.},
address = "";
Expand All @@ -365,6 +378,7 @@ proc serve*(server: AsyncHttpServer, port: Port,
#echo(f.isNil)
#echo(f.repr)


proc close*(server: AsyncHttpServer) =
## Terminates the async http server instance.
server.socket.close()
Expand Down

0 comments on commit 3803d5c

Please sign in to comment.