diff options
author | Gregory P. Smith <greg@krypto.org> | 2012-01-22 05:06:22 (GMT) |
---|---|---|
committer | Gregory P. Smith <greg@krypto.org> | 2012-01-22 05:06:22 (GMT) |
commit | 08c1278ab8d49f3b51a984c08cd4f8efe0fc6440 (patch) | |
tree | c94ff4f6eceb64845f4b271f285e7b12bf7b5738 | |
parent | 1577cf758b061b2b9ae7449b637e67eb05b6e803 (diff) | |
parent | 4842efcf972eee8acef0840ecca34a88945a99a7 (diff) | |
download | cpython-08c1278ab8d49f3b51a984c08cd4f8efe0fc6440.zip cpython-08c1278ab8d49f3b51a984c08cd4f8efe0fc6440.tar.gz cpython-08c1278ab8d49f3b51a984c08cd4f8efe0fc6440.tar.bz2 |
Fix FreeBSD, NetBSD and OpenBSD behavior of the issue #8052 fix.
-rw-r--r-- | Modules/_posixsubprocess.c | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 7407a11..3d4eb77 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -8,6 +8,9 @@ #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif +#if defined(HAVE_SYS_STAT_H) && defined(__FreeBSD__) +#include <sys/stat.h> +#endif #ifdef HAVE_SYS_SYSCALL_H #include <sys/syscall.h> #endif @@ -26,8 +29,11 @@ # endif #endif -#define LINUX_SOLARIS_FD_DIR "/proc/self/fd" -#define BSD_OSX_FD_DIR "/dev/fd" +#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)) +# define FD_DIR "/dev/fd" +#else +# define FD_DIR "/proc/self/fd" +#endif #define POSIX_CALL(call) if ((call) == -1) goto error @@ -64,6 +70,28 @@ static int _pos_int_from_ascii(char *name) } +#if defined(__FreeBSD__) +/* When /dev/fd isn't mounted it is often a static directory populated + * with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD and OpenBSD. + * NetBSD and OpenBSD have a /proc fs available (though not necessarily + * mounted) and do not have fdescfs for /dev/fd. MacOS X has a devfs + * that properly supports /dev/fd. + */ +static int _is_fdescfs_mounted_on_dev_fd() +{ + struct stat dev_stat; + struct stat dev_fd_stat; + if (stat("/dev", &dev_stat) != 0) + return 0; + if (stat(FD_DIR, &dev_fd_stat) != 0) + return 0; + if (dev_stat.st_dev == dev_fd_stat.st_dev) + return 0; /* / == /dev == /dev/fd means it is static. #fail */ + return 1; +} +#endif + + /* Returns 1 if there is a problem with fd_sequence, 0 otherwise. */ static int _sanity_check_python_fd_sequence(PyObject *fd_sequence) { @@ -171,8 +199,7 @@ static void _close_open_fd_range_safe(int start_fd, int end_fd, int fd_dir_fd; if (start_fd >= end_fd) return; - fd_dir_fd = open(LINUX_SOLARIS_FD_DIR, O_RDONLY | O_CLOEXEC, 0); - /* Not trying to open the BSD_OSX path as this is currently Linux only. */ + fd_dir_fd = open(FD_DIR, O_RDONLY | O_CLOEXEC, 0); if (fd_dir_fd == -1) { /* No way to get a list of open fds. */ _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep); @@ -239,9 +266,12 @@ static void _close_open_fd_range_maybe_unsafe(int start_fd, int end_fd, if (start_fd >= end_fd) return; - proc_fd_dir = opendir(BSD_OSX_FD_DIR); - if (!proc_fd_dir) - proc_fd_dir = opendir(LINUX_SOLARIS_FD_DIR); +#if defined(__FreeBSD__) + if (!_is_fdescfs_mounted_on_dev_fd()) + proc_fd_dir = NULL; + else +#endif + proc_fd_dir = opendir(FD_DIR); if (!proc_fd_dir) { /* No way to get a list of open fds. */ _close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep); @@ -363,8 +393,16 @@ static void child_exec(char *const exec_array[], POSIX_CALL(close(errwrite)); } - if (close_fds) - _close_open_fd_range(3, max_fd, py_fds_to_keep); + if (close_fds) { + int local_max_fd = max_fd; +#if defined(__NetBSD__) + local_max_fd = fcntl(0, F_MAXFD); + if (local_max_fd < 0) + local_max_fd = max_fd; +#endif + /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */ + _close_open_fd_range(3, local_max_fd, py_fds_to_keep); + } if (cwd) POSIX_CALL(chdir(cwd)); |