From 787410680b9866d56a1ec1915ebbf41ab5cac7a0 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Sat, 17 Aug 2002 11:41:01 +0000 Subject: Patch by Zack W to make test_noinherit() more robust: spawn a Python subprocess that does the right checks. This now works on Windows as well. --- Lib/test/test_tempfile.py | 51 ++++++++++++++++++++------------------------ Lib/test/tf_inherit_check.py | 25 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 Lib/test/tf_inherit_check.py diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 0e1c891..575986f 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -17,6 +17,7 @@ else: has_stat = 0 has_textmode = (tempfile._text_openflags != tempfile._bin_openflags) +has_spawnl = hasattr(os, 'spawnl') # TEST_FILES may need to be tweaked for systems depending on the maximum # number of files that can be opened at one time (see ulimit -n) @@ -323,39 +324,33 @@ class test__mkstemp_inner(TC): def test_noinherit(self): """_mkstemp_inner file handles are not inherited by child processes""" - # FIXME: Find a way to test this on Windows. - if os.name != 'posix': + if not has_spawnl: return # ugh, can't use TestSkipped. + if test_support.verbose: + v="v" + else: + v="q" + file = self.do_create() + fd = "%d" % file.fd - # We have to exec something, so that FD_CLOEXEC will take - # effect. The sanest thing to try is /bin/sh; we can easily - # instruct it to attempt to write to the fd and report success - # or failure. Unfortunately, sh syntax does not permit use of - # fds numerically larger than 9; abandon this test if so. - if file.fd > 9: - raise test_support.TestSkipped, 'cannot test with fd %d' % file.fd - - pid = os.fork() - if pid: - status = os.wait()[1] - self.failUnless(os.WIFEXITED(status), - "child process did not exit (status %d)" % status) - - # We want the child to have exited _un_successfully, indicating - # failure to write to the closed fd. - self.failUnless(os.WEXITSTATUS(status) != 0, - "child process exited successfully") + try: + me = __file__ + except NameError: + me = sys.argv[0] - else: - try: - # Throw away stderr. - nul = os.open('/dev/null', os.O_RDWR) - os.dup2(nul, 2) - os.execv('/bin/sh', ['sh', '-c', 'echo blat >&%d' % file.fd]) - except: - os._exit(0) + # We have to exec something, so that FD_CLOEXEC will take + # effect. The core of this test is therefore in + # tf_inherit_check.py, which see. + tester = os.path.join(os.path.dirname(os.path.abspath(me)), + "tf_inherit_check.py") + + retval = os.spawnl(os.P_WAIT, sys.executable, + sys.executable, tester, v, fd) + self.failIf(retval < 0, + "child process caught fatal signal %d" % -retval) + self.failIf(retval > 0, "child process reports failure") def test_textmode(self): """_mkstemp_inner can create files in text mode""" diff --git a/Lib/test/tf_inherit_check.py b/Lib/test/tf_inherit_check.py new file mode 100644 index 0000000..a8b80d2 --- /dev/null +++ b/Lib/test/tf_inherit_check.py @@ -0,0 +1,25 @@ +# Helper script for test_tempfile.py. argv[2] is the number of a file +# descriptor which should _not_ be open. Check this by attempting to +# write to it -- if we succeed, something is wrong. + +import sys +import os + +verbose = (sys.argv[1] == 'v') +try: + fd = int(sys.argv[2]) + + try: + os.write(fd, "blat") + except os.error: + # Success -- could not write to fd. + sys.exit(0) + else: + if verbose: + sys.stderr.write("fd %d is open in child" % fd) + sys.exit(1) + +except StandardError: + if verbose: + raise + sys.exit(1) -- cgit v0.12