summaryrefslogtreecommitdiff
path: root/Modules/_posixsubprocess.c
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2012-01-21 21:06:22 -0800
committerGregory P. Smith <greg@krypto.org>2012-01-21 21:06:22 -0800
commit4a14baa0c3902b2c664788cb3b07f5e736807a74 (patch)
treef5d744c9741dc899ddea0b729cf8733ab2e41ebd /Modules/_posixsubprocess.c
parent0aa2b19687b778aa6911ec09958cc2da293b2b6a (diff)
parentdc94d326cd3d9593ba276b280387e4430e0ec544 (diff)
downloadcpython-4a14baa0c3902b2c664788cb3b07f5e736807a74.tar.gz
Fix FreeBSD, NetBSD and OpenBSD behavior of the issue #8052 fix.
Diffstat (limited to 'Modules/_posixsubprocess.c')
-rw-r--r--Modules/_posixsubprocess.c56
1 files changed, 47 insertions, 9 deletions
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index 7407a11bc8..3d4eb7722c 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));