@@ -4485,6 +4485,61 @@ def test_openpty(self):
44854485 self .assertEqual (os .get_inheritable (master_fd ), False )
44864486 self .assertEqual (os .get_inheritable (slave_fd ), False )
44874487
4488+ @unittest .skipUnless (hasattr (os , 'spawnl' ), "need os.openpty()" )
4489+ def test_pipe_spawnl (self ):
4490+ # gh-77046: On Windows, os.pipe() file descriptors must be created with
4491+ # _O_NOINHERIT to make them non-inheritable. UCRT has no public API to
4492+ # get (_osfile(fd) & _O_NOINHERIT), so use a functional test.
4493+ #
4494+ # Make sure that fd is not inherited by a child process created by
4495+ # os.spawnl(): get_osfhandle() and dup() must fail with EBADF.
4496+
4497+ fd , fd2 = os .pipe ()
4498+ self .addCleanup (os .close , fd )
4499+ self .addCleanup (os .close , fd2 )
4500+
4501+ code = textwrap .dedent (f"""
4502+ import errno
4503+ import os
4504+ import test.support
4505+ try:
4506+ import msvcrt
4507+ except ImportError:
4508+ msvcrt = None
4509+
4510+ fd = { fd }
4511+
4512+ with test.support.SuppressCrashReport():
4513+ if msvcrt is not None:
4514+ try:
4515+ handle = msvcrt.get_osfhandle(fd)
4516+ except OSError as exc:
4517+ if exc.errno != errno.EBADF:
4518+ raise
4519+ # get_osfhandle(fd) failed with EBADF as expected
4520+ else:
4521+ raise Exception("get_osfhandle() must fail")
4522+
4523+ try:
4524+ fd3 = os.dup(fd)
4525+ except OSError as exc:
4526+ if exc.errno != errno.EBADF:
4527+ raise
4528+ # os.dup(fd) failed with EBADF as expected
4529+ else:
4530+ os.close(fd3)
4531+ raise Exception("dup must fail")
4532+ """ )
4533+
4534+ filename = os_helper .TESTFN
4535+ self .addCleanup (os_helper .unlink , os_helper .TESTFN )
4536+ with open (filename , "w" ) as fp :
4537+ print (code , file = fp , end = "" )
4538+
4539+ cmd = [sys .executable , filename ]
4540+ exitcode = os .spawnl (os .P_WAIT , cmd [0 ], * cmd )
4541+ self .assertEqual (exitcode , 0 )
4542+
44884543
44894544class PathTConverterTests (unittest .TestCase ):
44904545 # tuples of (function name, allows fd arguments, additional arguments to
0 commit comments