diff options
author | Andy Wingo <wingo@pobox.com> | 2012-02-08 20:08:15 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2012-02-14 22:47:15 +0100 |
commit | 7565b9fc09242b0adfd81f1390e75ced3f894078 (patch) | |
tree | 1e869b5f16d61e00b5719fd184bc5c9de06ac24e | |
parent | a01a9308f051ee1c7e214642d43a750dcd6dce7f (diff) | |
download | guile-7565b9fc09242b0adfd81f1390e75ced3f894078.tar.gz |
add file-port-close-on-exec?; popen takes advantage of it.
* libguile/fports.c (scm_i_evict_port): Use F_DUPFD_CLOEXEC if the port
is CLOEXEC.
(scm_file_port_close_on_exec_p): New interface.
(scm_i_fdes_to_port): Use F_GETFD on the fd to see if it is cloexec,
and if it is, mark it in the scm_t_fport. That way popen.scm won't
have to do anything about it.
* module/ice-9/popen.scm (ensure-fdes): No need for false-if-exception
here.
(open-process): Rework the port-for-each call to not bother with file
descriptors that are CLOEXEC.
-rw-r--r-- | libguile/fports.c | 33 | ||||
-rw-r--r-- | libguile/fports.h | 5 | ||||
-rw-r--r-- | module/ice-9/popen.scm | 21 |
3 files changed, 48 insertions, 11 deletions
diff --git a/libguile/fports.c b/libguile/fports.c index bb998e7c4..7807fcb07 100644 --- a/libguile/fports.c +++ b/libguile/fports.c @@ -1,5 +1,5 @@ /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - * 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + * 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -21,6 +21,7 @@ #define _LARGEFILE64_SOURCE /* ask for stat64 etc */ #define _GNU_SOURCE /* ask for LONG_LONG_MAX/LONG_LONG_MIN */ +#define _POSIX_C_SOURCE 200809L /* F_DUPFD_CLOEXEC */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -259,7 +260,13 @@ scm_i_evict_port (void *closure, SCM port) if ((fp != NULL) && (fp->fdes == fd)) { - fp->fdes = dup (fd); + if (fp->cloexec_p) + /* The result will be 3 or more. Presumably we don't want + to accidentally end on 0, 1, or 2. */ + fp->fdes = fcntl (fd, F_DUPFD_CLOEXEC, 3); + else + fp->fdes = dup (fd); + if (fp->fdes == -1) scm_syserror ("scm_evict_ports"); scm_set_port_revealed_x (port, scm_from_int (0)); @@ -284,6 +291,17 @@ SCM_DEFINE (scm_file_port_p, "file-port?", 1, 0, 0, #undef FUNC_NAME +SCM_DEFINE (scm_file_port_close_on_exec_p, "file-port-close-on-exec?", 1, 0, 0, + (SCM fport), + "Determine whether @var{fobj} was created with the @code{FD_CLOEXEC} flag set.") +#define FUNC_NAME s_scm_file_port_close_on_exec_p +{ + SCM_VALIDATE_OPFPORT (1, fport); + return scm_from_bool (SCM_FSTREAM (fport)->cloexec_p); +} +#undef FUNC_NAME + + static SCM sys_file_port_name_canonicalization; SCM_SYMBOL (sym_relative, "relative"); SCM_SYMBOL (sym_absolute, "absolute"); @@ -537,6 +555,7 @@ scm_i_fdes_to_port (int fdes, long mode_bits, SCM name) SCM port; scm_t_fport *fp; int flags; + int fd_flags; /* test that fdes is valid. */ #ifdef __MINGW32__ @@ -554,9 +573,19 @@ scm_i_fdes_to_port (int fdes, long mode_bits, SCM name) SCM_MISC_ERROR ("requested file mode not available on fdes", SCM_EOL); } +#ifdef F_GETFD + fd_flags = fcntl (fdes, F_GETFD, 0); +#else + fd_flags = 0; +#endif + if (fd_flags == -1) + SCM_SYSERROR; + fp = (scm_t_fport *) scm_gc_malloc_pointerless (sizeof (scm_t_fport), "file port"); fp->fdes = fdes; + fp->cloexec_p = fd_flags & FD_CLOEXEC ? 1 : 0; + fp->reserved = 0; port = scm_c_make_port (scm_tc16_fport, mode_bits, (scm_t_bits)fp); diff --git a/libguile/fports.h b/libguile/fports.h index 32b6a5947..7a1713187 100644 --- a/libguile/fports.h +++ b/libguile/fports.h @@ -3,7 +3,7 @@ #ifndef SCM_FPORTS_H #define SCM_FPORTS_H -/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2008, 2009, 2011 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2008, 2009, 2011, 2012 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -32,6 +32,8 @@ /* struct allocated for each buffered FPORT. */ typedef struct scm_t_fport { int fdes; /* file descriptor. */ + int cloexec_p : 1; + int reserved : 31; } scm_t_fport; SCM_API scm_t_bits scm_tc16_fport; @@ -54,6 +56,7 @@ SCM_API void scm_evict_ports (int fd); SCM_API SCM scm_open_file (SCM filename, SCM modes); SCM_API SCM scm_fdes_to_port (int fdes, char *mode, SCM name); SCM_API SCM scm_file_port_p (SCM obj); +SCM_API SCM scm_file_port_close_on_exec_p (SCM fport); SCM_INTERNAL void scm_init_fports (void); /* internal functions */ diff --git a/module/ice-9/popen.scm b/module/ice-9/popen.scm index b9debd444..805b7315c 100644 --- a/module/ice-9/popen.scm +++ b/module/ice-9/popen.scm @@ -1,6 +1,6 @@ ;; popen emulation, for non-stdio based ports. -;;;; Copyright (C) 1998, 1999, 2000, 2001, 2003, 2006, 2010, 2011 Free Software Foundation, Inc. +;;;; Copyright (C) 1998, 1999, 2000, 2001, 2003, 2006, 2010, 2011, 2012 Free Software Foundation, Inc. ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public @@ -39,7 +39,9 @@ (define port/pid-table (make-weak-key-hash-table 31)) (define (ensure-fdes port mode) - (or (false-if-exception (fileno port)) + (or (and (file-port? port) + (not (port-closed? port)) + (fileno port)) (open-fdes *null-device* mode))) ;; run a process connected to an input, an output or an @@ -88,12 +90,15 @@ ;; flushing port buffers or evicting ports. (port-for-each (lambda (pt-entry) - (false-if-exception - (let ((pt-fileno (fileno pt-entry))) - (if (not (or (= pt-fileno input-fdes) - (= pt-fileno output-fdes) - (= pt-fileno error-fdes))) - (close-fdes pt-fileno)))))) + (if (and (file-port? pt-entry) + (not (port-closed? pt-entry)) + (not (file-port-close-on-exec? pt-entry))) + (let ((pt-fileno (fileno pt-entry))) + (if (not (or (= pt-fileno input-fdes) + (= pt-fileno output-fdes) + (= pt-fileno error-fdes))) + (false-if-exception + (close-fdes pt-fileno))))))) ;; Copy the three selected descriptors to the standard ;; descriptors 0, 1, 2, if not already there |