diff mbox

[libgfortran] Set close-on-exec flag when opening files

Message ID CAO9iq9FjkYuu6fQop5Ss2yTiimVB74qNcryjedu2x4j39aKu_w@mail.gmail.com
State New
Headers show

Commit Message

Janne Blomqvist Oct. 29, 2013, 11:39 p.m. UTC
Hello,

the attached patch sets the close-on-exec flag when opening files, as
is usually considered good practice these days. See e.g.
http://www.python.org/dev/peps/pep-0446/ and links therein for more
information.

The preconnected units INPUT_UNIT, OUTPUT_UNIT, ERROR_UNIT are not
affected, only new units created with the OPEN statement. In the
(very!?) unlikely event that someone really needs Fortran units to be
inherited to child processes, the close-on-exec flag can be cleared
with fcntl() before calling one of the exec() family functions.

Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

2013-10-30  Janne Blomqvist  <jb@gcc.gnu.org>

    * configure.ac: Check presence of mkostemp.
    * io/unix.c (set_close_on_exec): New function.
    (tempfile_open): Use mkostemp and O_CLOEXEC if available, fallback
    to calling set_close_on_exec.
    (regular_file): Add O_CLOEXEC to flags if defined.
    (open_external): Call set_close_on_exec if O_CLOEXEC is not
    defined.
    * config.h.in: Regenerated.
    * configure: Regenerated.

Comments

Janne Blomqvist Nov. 5, 2013, 10:24 p.m. UTC | #1
PING

On Wed, Oct 30, 2013 at 1:39 AM, Janne Blomqvist
<blomqvist.janne@gmail.com> wrote:
> Hello,
>
> the attached patch sets the close-on-exec flag when opening files, as
> is usually considered good practice these days. See e.g.
> http://www.python.org/dev/peps/pep-0446/ and links therein for more
> information.
>
> The preconnected units INPUT_UNIT, OUTPUT_UNIT, ERROR_UNIT are not
> affected, only new units created with the OPEN statement. In the
> (very!?) unlikely event that someone really needs Fortran units to be
> inherited to child processes, the close-on-exec flag can be cleared
> with fcntl() before calling one of the exec() family functions.
>
> Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
>
> 2013-10-30  Janne Blomqvist  <jb@gcc.gnu.org>
>
>     * configure.ac: Check presence of mkostemp.
>     * io/unix.c (set_close_on_exec): New function.
>     (tempfile_open): Use mkostemp and O_CLOEXEC if available, fallback
>     to calling set_close_on_exec.
>     (regular_file): Add O_CLOEXEC to flags if defined.
>     (open_external): Call set_close_on_exec if O_CLOEXEC is not
>     defined.
>     * config.h.in: Regenerated.
>     * configure: Regenerated.
>
>
> --
> Janne Blomqvist
Tobias Burnus Nov. 10, 2013, 5:16 p.m. UTC | #2
Janne Blomqvist wrote:
> the attached patch sets the close-on-exec flag when opening files, as
> is usually considered good practice these days. See e.g.
> http://www.python.org/dev/peps/pep-0446/  and links therein for more
> information.

> +  int flags = O_RDWR|O_CREAT|O_EXCL;
I'd add spaces around "|".


Otherwise, it looks good to me. Thanks for the patch and sorry for the 
slow review.

Tobias
diff mbox

Patch

diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 4609eba..6417373 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -280,7 +280,7 @@  else
    strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
    getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \
    readlink getgid getpid getppid getuid geteuid umask getegid \
-   secure_getenv __secure_getenv)
+   secure_getenv __secure_getenv mkostemp)
 fi
 
 # Check strerror_r, cannot be above as versions with two and three arguments exist
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index dd2715b..ae48d57 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -1070,6 +1070,19 @@  unpack_filename (char *cstring, const char *fstring, int len)
 }
 
 
+/* Set the close-on-exec flag for an existing fd, if the system
+   supports such.  */
+
+static void
+set_close_on_exec (int fd __attribute__ ((unused)))
+{
+  /* Mingw does not define F_SETFD.  */
+#if defined(F_SETFD) && defined(FD_CLOEXEC)
+  fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+}
+
+
 /* Helper function for tempfile(). Tries to open a temporary file in
    the directory specified by tempdir. If successful, the file name is
    stored in fname and the descriptor returned. Returns -1 on
@@ -1109,7 +1122,12 @@  tempfile_open (const char *tempdir, char **fname)
   mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
 #endif
 
+#if defined(HAVE_MKOSTEMP) && defined(O_CLOEXEC)
+  fd = mkostemp (template, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
+#else
   fd = mkstemp (template);
+  set_close_on_exec (fd);
+#endif
 
 #ifdef HAVE_UMASK
   (void) umask (mode_mask);
@@ -1119,6 +1137,13 @@  tempfile_open (const char *tempdir, char **fname)
   fd = -1;
   int count = 0;
   size_t slashlen = strlen (slash);
+  int flags = O_RDWR|O_CREAT|O_EXCL;
+#if defined(HAVE_CRLF) && defined(O_BINARY)
+  flags |= O_BINARY;
+#endif
+#ifdef O_CLOEXEC
+  flags |= O_CLOEXEC;
+#endif
   do
     {
       snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX", 
@@ -1142,14 +1167,12 @@  tempfile_open (const char *tempdir, char **fname)
 	continue;
       }
 
-#if defined(HAVE_CRLF) && defined(O_BINARY)
-      fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
-		 S_IRUSR | S_IWUSR);
-#else
-      fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-#endif
+      fd = open (template, flags, S_IRUSR | S_IWUSR);
     }
   while (fd == -1 && errno == EEXIST);
+#ifndef O_CLOEXEC
+  set_close_on_exec (fd);
+#endif
 #endif /* HAVE_MKSTEMP */
 
   *fname = template;
@@ -1323,6 +1346,10 @@  regular_file (st_parameter_open *opp, unit_flags *flags)
   crflag |= O_BINARY;
 #endif
 
+#ifdef O_CLOEXEC
+  crflag |= O_CLOEXEC;
+#endif
+
   mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
   fd = open (path, rwflag | crflag, mode);
   if (flags->action != ACTION_UNSPECIFIED)
@@ -1386,6 +1413,9 @@  open_external (st_parameter_open *opp, unit_flags *flags)
       /* regular_file resets flags->action if it is ACTION_UNSPECIFIED and
        * if it succeeds */
       fd = regular_file (opp, flags);
+#ifndef O_CLOEXEC
+      set_close_on_exec (fd);
+#endif
     }
 
   if (fd < 0)