-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fd leak in Unix.ml? #5421
Description
Original bug ID: 5421
Reporter: hw
Assigned to: @protz
Status: closed (set by @xavierleroy on 2013-08-31T10:44:25Z)
Resolution: fixed
Severity: major
Platform: x86_64
OS: CentOS
OS Version: 5.5
Version: 3.12.1
Fixed in version: 3.13.0+dev
Category: ~DO NOT USE (was: OCaml general)
Monitored by: hw @protz
Bug description
I have an OCaml process that is leaking fds in multiples of 6. In the logs I have:
Unix.Unix_error(ENOMEM, "fork", "")
Raised by primitive operation at file "unix.ml", line 865, characters 8-14
Called from file "unix.ml", line 882, characters 2-141
[...]
Looking at otherlibs/unix/unix.ml in the source distribution, this corresponds to a call to open_process_full (line 882).
let open_process_full cmd env =
let (in_read, in_write) = pipe() in
let (out_read, out_write) = pipe() in
let (err_read, err_write) = pipe() in
let inchan = in_channel_of_descr in_read in
let outchan = out_channel_of_descr out_write in
let errchan = in_channel_of_descr err_read in
open_proc_full cmd env (Process_full(inchan, outchan, errchan))
out_read in_write err_write [in_read; out_write; err_read];
close out_read;
close in_write;
close err_write;
(inchan, outchan, errchan)
open_process_full in turn calls open_proc_full, which calls fork() (line 865). Matching up the timestamps with an strace:
19188 12:39:29 pipe([223, 224]) = 0
19188 12:39:29 pipe([225, 226]) = 0
19188 12:39:29 pipe([227, 228]) = 0
19188 12:39:29 futex(0x9b0174, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x9b0170, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1} <unfinished ...>
19188 12:39:29 <... futex resumed> ) = 1
19188 12:39:29 lseek(223, 0, SEEK_CUR <unfinished ...>
19188 12:39:29 <... lseek resumed> ) = -1 ESPIPE (Illegal seek)
19188 12:39:29 futex(0x9b0174, FUTEX_WAIT_PRIVATE, 116925, NULL <unfinished ...>
19188 12:39:29 <... futex resumed> ) = 0
19188 12:39:29 futex(0x9b0140, FUTEX_WAKE_PRIVATE, 1) = 0
19188 12:39:29 lseek(226, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
19188 12:39:29 lseek(227, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
19188 12:39:29 fcntl(223, F_GETFD) = 0
19188 12:39:29 fcntl(223, F_SETFD, FD_CLOEXEC) = 0
19188 12:39:29 fcntl(226, F_GETFD) = 0
19188 12:39:29 fcntl(226, F_SETFD, FD_CLOEXEC) = 0
19188 12:39:29 fcntl(227, F_GETFD) = 0
19188 12:39:29 fcntl(227, F_SETFD, FD_CLOEXEC) = 0
19188 12:39:29 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x447169d0) = -1 ENOMEM (Cannot allocate memory)
clone() is failing in one of the dozen or so ways documented in 'man 2 clone'. This exception propagates out of open_process_full, leaving the six fds from the three pipe() calls hanging around. As far as I can tell these fds are not cleaned up by any garbage collection process.
fds 223-228 are still open a few hours later. Soon the process will hit ulimit -n.