In the interests of being insensitive to execution environments aka reproducibility, you probably want to precede that @mrhdias program with: import posix var fdLim: RLimit discard getrlimit(RLIMIT_NOFILE, fdLim) fdLim.rlim_cur = 1024 # fdLim.rlim_max echo "max-max fd ", fdLim.rlim_max, " soft ", fdLim.rlim_cur discard setrlimit(RLIMIT_NOFILE, fdLim) Run
On Linux, the hard limit is usually configured in `/etc/security/limits.conf`. Editing that (as root) does not take effect immediately. Re-logging in via ssh or /bin/login should make it active, but a reboot definitely will. You can inspect soft&hard limits in effect with `cat /proc/$$/limits` (more shell-portable/less OS-portable than limit/ulimit). \-- As I mentioned earlier in this thread with a link to more details, "asyncfile" is (at least on Unix) [false advertising](https://forum.nim-lang.org/t/6512#40229). Regular file IO is not async unless you use [special purpose OS APIs](https://stackoverflow.com/questions/87892/what-is-the-status-of-posix-asynchronous-i-o-aio) or do [a non-standard system/app service](https://forum.nim-lang.org/t/6889#43136). So, it is no loss of concurrency to clients to make your IO loop: var mf = memfiles.open(path) # raises if path missing/etc. ... var off = 0 while off < mf.size: let data = cast[pointer](cast[int](mf.mem) + off) await req.client.send(data, min(chunkSize, mf.size - off)) off += chunkSize mf.close Run where you use `$mf.size` in your MIME type header code. I know this may only mask/delay your underlying problem, but I thought explicitness might help. \-- Also, on Unix the lowest numbered file descriptor slot is always used if available. So, you do not need to iterate over /proc/PID/fd as per @treeform advice - you can just observe the maximum number fd in use in your program itself, though these may be unexposed/unexported by the stock Nim. (Indeed, if you read docs on those limits they often just say 1 + max fd ever issued by the kernel, not "number of fds" because these ideas are basically the same.) If you run your server under `strace -o bug.st` then you should be able to see if file descriptors being returned in system calls/passed around to others are "staying small numbers like 0..10" or "skyrocketing to 1024". The latter indicates a leak.