Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4842efc

Browse files
committed
Fix FreeBSD, NetBSD and OpenBSD behavior of the issue #8052 fix.
1 parent df300d5 commit 4842efc

1 file changed

Lines changed: 47 additions & 9 deletions

File tree

Modules/_posixsubprocess.c

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#ifdef HAVE_SYS_TYPES_H
99
#include <sys/types.h>
1010
#endif
11+
#if defined(HAVE_SYS_STAT_H) && defined(__FreeBSD__)
12+
#include <sys/stat.h>
13+
#endif
1114
#ifdef HAVE_SYS_SYSCALL_H
1215
#include <sys/syscall.h>
1316
#endif
@@ -26,8 +29,11 @@
2629
# endif
2730
#endif
2831

29-
#define LINUX_SOLARIS_FD_DIR "/proc/self/fd"
30-
#define BSD_OSX_FD_DIR "/dev/fd"
32+
#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__))
33+
# define FD_DIR "/dev/fd"
34+
#else
35+
# define FD_DIR "/proc/self/fd"
36+
#endif
3137

3238
#define POSIX_CALL(call) if ((call) == -1) goto error
3339

@@ -62,6 +68,28 @@ static int _pos_int_from_ascii(char *name)
6268
}
6369

6470

71+
#if defined(__FreeBSD__)
72+
/* When /dev/fd isn't mounted it is often a static directory populated
73+
* with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD and OpenBSD.
74+
* NetBSD and OpenBSD have a /proc fs available (though not necessarily
75+
* mounted) and do not have fdescfs for /dev/fd. MacOS X has a devfs
76+
* that properly supports /dev/fd.
77+
*/
78+
static int _is_fdescfs_mounted_on_dev_fd()
79+
{
80+
struct stat dev_stat;
81+
struct stat dev_fd_stat;
82+
if (stat("/dev", &dev_stat) != 0)
83+
return 0;
84+
if (stat(FD_DIR, &dev_fd_stat) != 0)
85+
return 0;
86+
if (dev_stat.st_dev == dev_fd_stat.st_dev)
87+
return 0; /* / == /dev == /dev/fd means it is static. #fail */
88+
return 1;
89+
}
90+
#endif
91+
92+
6593
/* Returns 1 if there is a problem with fd_sequence, 0 otherwise. */
6694
static int _sanity_check_python_fd_sequence(PyObject *fd_sequence)
6795
{
@@ -169,8 +197,7 @@ static void _close_open_fd_range_safe(int start_fd, int end_fd,
169197
int fd_dir_fd;
170198
if (start_fd >= end_fd)
171199
return;
172-
fd_dir_fd = open(LINUX_SOLARIS_FD_DIR, O_RDONLY | O_CLOEXEC, 0);
173-
/* Not trying to open the BSD_OSX path as this is currently Linux only. */
200+
fd_dir_fd = open(FD_DIR, O_RDONLY | O_CLOEXEC, 0);
174201
if (fd_dir_fd == -1) {
175202
/* No way to get a list of open fds. */
176203
_close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
@@ -237,9 +264,12 @@ static void _close_open_fd_range_maybe_unsafe(int start_fd, int end_fd,
237264
if (start_fd >= end_fd)
238265
return;
239266

240-
proc_fd_dir = opendir(BSD_OSX_FD_DIR);
241-
if (!proc_fd_dir)
242-
proc_fd_dir = opendir(LINUX_SOLARIS_FD_DIR);
267+
#if defined(__FreeBSD__)
268+
if (!_is_fdescfs_mounted_on_dev_fd())
269+
proc_fd_dir = NULL;
270+
else
271+
#endif
272+
proc_fd_dir = opendir(FD_DIR);
243273
if (!proc_fd_dir) {
244274
/* No way to get a list of open fds. */
245275
_close_fds_by_brute_force(start_fd, end_fd, py_fds_to_keep);
@@ -361,8 +391,16 @@ static void child_exec(char *const exec_array[],
361391
POSIX_CALL(close(errwrite));
362392
}
363393

364-
if (close_fds)
365-
_close_open_fd_range(3, max_fd, py_fds_to_keep);
394+
if (close_fds) {
395+
int local_max_fd = max_fd;
396+
#if defined(__NetBSD__)
397+
local_max_fd = fcntl(0, F_MAXFD);
398+
if (local_max_fd < 0)
399+
local_max_fd = max_fd;
400+
#endif
401+
/* TODO HP-UX could use pstat_getproc() if anyone cares about it. */
402+
_close_open_fd_range(3, local_max_fd, py_fds_to_keep);
403+
}
366404

367405
if (cwd)
368406
POSIX_CALL(chdir(cwd));

0 commit comments

Comments
 (0)