Deno: file_server returns Too many open files error

Created on 13 Feb 2020  路  2Comments  路  Source: denoland/deno

I simply run file_server, but it will start returning the error with 500 status.

deno 0.32.0
v8 8.1.108
typescript 3.7.2

deno run --allow-net --allow-read https://deno.land/std/http/file_server.ts .

This is the my test case.

const url = 'http://localhost:4500/public/index.html';

let count = 0;
(async () => {
  while (true) {
    console.log('opening...', ++count);
    const res = await fetch(url);
    if (res.status !== 200) {
      console.log('error!.', res.status);
    } else {
      console.log('opened.', res.status);
    }
  }
})();

If I increase ulimit, the error can be delayed, but it won't fix the issue.

I have tested some cases, it seems files are not closed properly.
If I close files after returning responses, it won't cause the error.

async function serveFile(req: ServerRequest, filePath: string) {
  const [file, fileInfo] = await Promise.all([open(filePath), stat(filePath)]);
  const headers = new Headers();
  headers.set('content-length', fileInfo.len.toString());
  headers.set('content-type', 'text/plain; charset=utf-8');

  const res = {
    status: 200,
    body: file,
    headers,
  };
  return res;
}

window.onload = async function main() {
  const addr = '0.0.0.0:4500';
  const server = serve(addr);
  console.log(`HTTP server listening on http://${addr}/`);
  for await (const req of server) {
    const res = await serveFile(req, 'public/index.html');
    await req.respond(res);
    res.body.close(); // <- here
  }
};

https://github.com/suguru03/file-server-demo

bug

Most helpful comment

@suguru03 your findings that res.body.close() fixes the problem is correct. When fetch returns a response, the body of response is stored as Deno resource. Therefor body has to be consumed or closed manually.

There was a try to address this problem by @kevinkassimo in #2106, but it did not land.

All 2 comments

@suguru03 your findings that res.body.close() fixes the problem is correct. When fetch returns a response, the body of response is stored as Deno resource. Therefor body has to be consumed or closed manually.

There was a try to address this problem by @kevinkassimo in #2106, but it did not land.

I solved this issue in my code (which is based on https://deno.land/std/http/file_server.ts) by defining this type guard:

function isCloser(object: any): object is Deno.Closer {
    return 'close' in object;
}

And then at the end of the finally block in listenAndServe:

if (isCloser(response.body)) {
    response.body.close();
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

benjamingr picture benjamingr  路  3Comments

sh7dm picture sh7dm  路  3Comments

ry picture ry  路  3Comments

doutchnugget picture doutchnugget  路  3Comments

justjavac picture justjavac  路  3Comments