diff --git a/Changes b/Changes index e673d5e71..771120afb 100644 --- a/Changes +++ b/Changes @@ -66,6 +66,10 @@ Standard library: - Add optimized composition operators |> and @@ in Pervasives +Other libraries: +- PR#5568: add O_CLOEXEC flag to Unix.openfile, so that the returned + file descriptor is created in close-on-exec mode + Runtime system: * PR#6019: more efficient implementation of caml_modify() and caml_initialize(). The new implementations are less lenient than the old ones: now, diff --git a/otherlibs/unix/open.c b/otherlibs/unix/open.c index 097a0455b..ecee01389 100644 --- a/otherlibs/unix/open.c +++ b/otherlibs/unix/open.c @@ -17,6 +17,9 @@ #include #include "unixsupport.h" #include +#ifdef HAS_UNISTD +#include +#endif #include #ifndef O_NONBLOCK @@ -31,16 +34,31 @@ #ifndef O_RSYNC #define O_RSYNC 0 #endif +#ifndef O_CLOEXEC +#define NEED_CLOEXEC_EMULATION +#define O_CLOEXEC 0 +#endif -static int open_flag_table[] = { +static int open_flag_table[14] = { O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL, - O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC, 0 + O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC, + 0, /* O_SHARE_DELETE, Windows-only */ + O_CLOEXEC }; +#ifdef NEED_CLOEXEC_EMULATION +static int open_cloexec_table[14] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + 0, + 1 +}; +#endif + CAMLprim value unix_open(value path, value flags, value perm) { CAMLparam3(path, flags, perm); - int ret, cv_flags; + int fd, cv_flags; char * p; cv_flags = convert_flag_list(flags, open_flag_table); @@ -48,9 +66,17 @@ CAMLprim value unix_open(value path, value flags, value perm) strcpy(p, String_val(path)); /* open on a named FIFO can block (PR#1533) */ enter_blocking_section(); - ret = open(p, cv_flags, Int_val(perm)); + fd = open(p, cv_flags, Int_val(perm)); leave_blocking_section(); stat_free(p); - if (ret == -1) uerror("open", path); - CAMLreturn (Val_int(ret)); + if (fd == -1) uerror("open", path); +#if defined(NEED_CLOEXEC_EMULATION) && defined(FD_CLOEXEC) + if (convert_flag_list(flags, open_cloexec_table) != 0) { + int flags = fcntl(fd, F_GETFD, 0); + if (flags == -1 || + fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + uerror("open", path); + } +#endif + CAMLreturn (Val_int(fd)); } diff --git a/otherlibs/unix/unix.ml b/otherlibs/unix/unix.ml index 8a69ca7b4..a89783146 100644 --- a/otherlibs/unix/unix.ml +++ b/otherlibs/unix/unix.ml @@ -227,6 +227,7 @@ type open_flag = | O_SYNC | O_RSYNC | O_SHARE_DELETE + | O_CLOEXEC type file_perm = int diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli index a9b551041..6c4202246 100644 --- a/otherlibs/unix/unix.mli +++ b/otherlibs/unix/unix.mli @@ -242,6 +242,9 @@ type open_flag = O_SYNC/O_DSYNC) *) | O_SHARE_DELETE (** Windows only: allow the file to be deleted while still open *) + | O_CLOEXEC (** Set the close-on-exec flag on the + descriptor returned by {!openfile} *) + (** The flags to {!Unix.openfile}. *) diff --git a/otherlibs/unix/unixLabels.mli b/otherlibs/unix/unixLabels.mli index 91636c6a8..7494d4f7b 100644 --- a/otherlibs/unix/unixLabels.mli +++ b/otherlibs/unix/unixLabels.mli @@ -239,6 +239,8 @@ type open_flag = Unix.open_flag = | O_SYNC (** Writes complete as `Synchronised I/O file integrity completion' *) | O_RSYNC (** Reads complete as writes (depending on O_SYNC/O_DSYNC) *) | O_SHARE_DELETE (** Windows only: allow the file to be deleted while still open *) + | O_CLOEXEC (** Set the close-on-exec flag on the + descriptor returned by {!openfile} *) (** The flags to {!UnixLabels.openfile}. *) diff --git a/otherlibs/win32unix/open.c b/otherlibs/win32unix/open.c index 40ea34b63..a2ffa4e1e 100644 --- a/otherlibs/win32unix/open.c +++ b/otherlibs/win32unix/open.c @@ -16,22 +16,26 @@ #include "unixsupport.h" #include -static int open_access_flags[13] = { +static int open_access_flags[14] = { GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int open_create_flags[13] = { - 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL, 0, 0, 0, 0, 0 +static int open_create_flags[14] = { + 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL, 0, 0, 0, 0, 0, 0 }; -static int open_share_flags[13] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FILE_SHARE_DELETE +static int open_share_flags[14] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FILE_SHARE_DELETE, 0 +}; + +static int open_cloexec_flags[14] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; CAMLprim value unix_open(value path, value flags, value perm) { - int fileaccess, createflags, fileattrib, filecreate, sharemode; + int fileaccess, createflags, fileattrib, filecreate, sharemode, cloexec; SECURITY_ATTRIBUTES attr; HANDLE h; @@ -55,9 +59,10 @@ CAMLprim value unix_open(value path, value flags, value perm) else fileattrib = FILE_ATTRIBUTE_NORMAL; + cloexec = convert_flag_list(flags, open_cloexec_flags); attr.nLength = sizeof(attr); attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = TRUE; + attr.bInheritHandle = cloexec ? FALSE : TRUE; h = CreateFile(String_val(path), fileaccess, sharemode, &attr, diff --git a/otherlibs/win32unix/unix.ml b/otherlibs/win32unix/unix.ml index a8a3dcc2a..cff003994 100644 --- a/otherlibs/win32unix/unix.ml +++ b/otherlibs/win32unix/unix.ml @@ -169,6 +169,7 @@ type open_flag = | O_SYNC | O_RSYNC | O_SHARE_DELETE + | O_CLOEXEC type file_perm = int