[erlang-bugs] Unix spawn driver does not close all file descriptors in child process

Matthew Dempsky matthew@REDACTED
Mon Mar 3 03:30:38 CET 2008


In erts/emulator/sys/unix/sys.c, spawn_start() only closes file
descriptors up to max_files-1, but there may be file descriptors open
greater than that.

E.g., on OS X 10.5 (checkfds.c is listed below):

1> [file:open("/dev/null", [read]) || _ <- lists:seq(1, 1016)], ok.
ok
2> Port = erlang:open_port({spawn, "./checkfds"}, [stream, in]).
#Port<0.4184>
3> receive {Port, {data, Data}} -> Data after 100 -> timeout end.
"0 1 2 1024 \n"

Erlang caps max_files to 1024 on unix systems where poll is
unavailable/broken (e.g., OS X) even when the file descriptor limit is
higher.  Also, in spawn_start, Erlang doesn't verify that pipe file
descriptors that will be closed in the parent process (e.g., ifd[1]
and ofd[0]) are less than max_files.  As a consequence, when nearly
all 1024 file descriptors are in use, some files might leak into the
child process.

I think instead spawn_start() should try closing all file descriptors
up to sysconf(_SC_OPEN_MAX).


checkfds.c:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
  int i, max;

  max = sysconf(_SC_OPEN_MAX);
  if (max == -1) max = 8192; /* XXX */

  for (i = 0; i < 8192; ++i)
    if (fcntl(i, F_GETFD) != -1)
      printf("%d ", i);
  printf("\n");

  return 0;
}



More information about the erlang-bugs mailing list