File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1972,6 +1972,23 @@ def test_leak_fast_process_del_killed(self):
19721972 self .assertRaises (OSError , os .waitpid , pid , 0 )
19731973 self .assertNotIn (ident , [id (o ) for o in subprocess ._active ])
19741974
1975+ def test_close_fds_after_preexec (self ):
1976+ fd_status = support .findfile ("fd_status.py" , subdir = "subprocessdata" )
1977+
1978+ # this FD is used as dup2() target by preexec_fn, and should be closed
1979+ # in the child process
1980+ fd = os .dup (1 )
1981+ self .addCleanup (os .close , fd )
1982+
1983+ p = subprocess .Popen ([sys .executable , fd_status ],
1984+ stdout = subprocess .PIPE , close_fds = True ,
1985+ preexec_fn = lambda : os .dup2 (1 , fd ))
1986+ output , ignored = p .communicate ()
1987+
1988+ remaining_fds = set (map (int , output .split (b',' )))
1989+
1990+ self .assertNotIn (fd , remaining_fds )
1991+
19751992
19761993@unittest .skipUnless (mswindows , "Windows specific tests" )
19771994class Win32ProcessTestCase (BaseTestCase ):
Original file line number Diff line number Diff line change @@ -412,17 +412,6 @@ child_exec(char *const exec_array[],
412412 POSIX_CALL (close (errwrite ));
413413 }
414414
415- if (close_fds ) {
416- int local_max_fd = max_fd ;
417- #if defined(__NetBSD__ )
418- local_max_fd = fcntl (0 , F_MAXFD );
419- if (local_max_fd < 0 )
420- local_max_fd = max_fd ;
421- #endif
422- /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */
423- _close_open_fd_range (3 , local_max_fd , py_fds_to_keep );
424- }
425-
426415 if (cwd )
427416 POSIX_CALL (chdir (cwd ));
428417
@@ -451,6 +440,18 @@ child_exec(char *const exec_array[],
451440 /* Py_DECREF(result); - We're about to exec so why bother? */
452441 }
453442
443+ /* close FDs after executing preexec_fn, which might open FDs */
444+ if (close_fds ) {
445+ int local_max_fd = max_fd ;
446+ #if defined(__NetBSD__ )
447+ local_max_fd = fcntl (0 , F_MAXFD );
448+ if (local_max_fd < 0 )
449+ local_max_fd = max_fd ;
450+ #endif
451+ /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */
452+ _close_open_fd_range (3 , local_max_fd , py_fds_to_keep );
453+ }
454+
454455 /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
455456 /* given the executable_list generated by Lib/subprocess.py. */
456457 saved_errno = 0 ;
You can’t perform that action at this time.
0 commit comments