[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