[Python-checkins] r78552 - in python/branches/py3k: Lib/test/test_thread.py Misc/NEWS Modules/posixmodule.c Python/import.c

gregory.p.smith python-checkins at python.org
Mon Mar 1 07:18:42 CET 2010


Author: gregory.p.smith
Date: Mon Mar  1 07:18:41 2010
New Revision: 78552

Log:
Merged revisions 78527,78550 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r78527 | gregory.p.smith | 2010-02-28 17:22:39 -0800 (Sun, 28 Feb 2010) | 4 lines
  
  Issue #7242: On Solaris 9 and earlier calling os.fork() from within a
  thread could raise an incorrect RuntimeError about not holding the import
  lock.  The import lock is now reinitialized after fork.
........
  r78550 | gregory.p.smith | 2010-02-28 22:01:02 -0800 (Sun, 28 Feb 2010) | 2 lines
  
  Fix test to be skipped on windows.
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Lib/test/test_thread.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/posixmodule.c
   python/branches/py3k/Python/import.c

Modified: python/branches/py3k/Lib/test/test_thread.py
==============================================================================
--- python/branches/py3k/Lib/test/test_thread.py	(original)
+++ python/branches/py3k/Lib/test/test_thread.py	Mon Mar  1 07:18:41 2010
@@ -4,6 +4,7 @@
 from test import support
 import _thread as thread
 import time
+import sys
 import weakref
 
 from test import lock_tests
@@ -193,8 +194,47 @@
     locktype = thread.allocate_lock
 
 
+class TestForkInThread(unittest.TestCase):
+    def setUp(self):
+        self.read_fd, self.write_fd = os.pipe()
+
+    @unittest.skipIf(sys.platform.startswith('win'),
+                    "This test is only appropriate for POSIX-like systems.")
+    def test_forkinthread(self):
+        def thread1():
+            try:
+                pid = os.fork() # fork in a thread
+            except RuntimeError:
+                os._exit(1) # exit the child
+
+            if pid == 0: # child
+                try:
+                    os.close(self.read_fd)
+                    os.write(self.write_fd, b"OK")
+                finally:
+                    os._exit(0)
+            else: # parent
+                os.close(self.write_fd)
+
+        thread.start_new_thread(thread1, ())
+        self.assertEqual(os.read(self.read_fd, 2), b"OK",
+                         "Unable to fork() in thread")
+
+    def tearDown(self):
+        try:
+            os.close(self.read_fd)
+        except OSError:
+            pass
+
+        try:
+            os.close(self.write_fd)
+        except OSError:
+            pass
+
+
 def test_main():
-    support.run_unittest(ThreadRunningTests, BarrierTest, LockTests)
+    support.run_unittest(ThreadRunningTests, BarrierTest, LockTests,
+                         TestForkInThread)
 
 if __name__ == "__main__":
     test_main()

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Mon Mar  1 07:18:41 2010
@@ -751,6 +751,10 @@
 - Expat: Fix DoS via XML document with malformed UTF-8 sequences
   (CVE_2009_3560).
 
+- Issue #7242: On Solaris 9 and earlier calling os.fork() from within a
+  thread could raise an incorrect RuntimeError about not holding the import
+  lock.  The import lock is now reinitialized after fork.
+
 - Issue #7999: os.setreuid() and os.setregid() would refuse to accept a -1
   parameter on some platforms such as OS X.
 

Modified: python/branches/py3k/Modules/posixmodule.c
==============================================================================
--- python/branches/py3k/Modules/posixmodule.c	(original)
+++ python/branches/py3k/Modules/posixmodule.c	Mon Mar  1 07:18:41 2010
@@ -3723,14 +3723,18 @@
 posix_fork1(PyObject *self, PyObject *noargs)
 {
 	pid_t pid;
-	int result;
+	int result = 0;
 	_PyImport_AcquireLock();
 	pid = fork1();
-	result = _PyImport_ReleaseLock();
+	if (pid == 0) {
+		/* child: this clobbers and resets the import lock. */
+		PyOS_AfterFork();
+	} else {
+		/* parent: release the import lock. */
+		result = _PyImport_ReleaseLock();
+	}
 	if (pid == -1)
 		return posix_error();
-	if (pid == 0)
-		PyOS_AfterFork();
 	if (result < 0) {
 		/* Don't clobber the OSError if the fork failed. */
 		PyErr_SetString(PyExc_RuntimeError,
@@ -3752,14 +3756,18 @@
 posix_fork(PyObject *self, PyObject *noargs)
 {
 	pid_t pid;
-	int result;
+	int result = 0;
 	_PyImport_AcquireLock();
 	pid = fork();
-	result = _PyImport_ReleaseLock();
+	if (pid == 0) {
+		/* child: this clobbers and resets the import lock. */
+		PyOS_AfterFork();
+	} else {
+		/* parent: release the import lock. */
+		result = _PyImport_ReleaseLock();
+	}
 	if (pid == -1)
 		return posix_error();
-	if (pid == 0)
-		PyOS_AfterFork();
 	if (result < 0) {
 		/* Don't clobber the OSError if the fork failed. */
 		PyErr_SetString(PyExc_RuntimeError,
@@ -3877,11 +3885,12 @@
 
 	_PyImport_AcquireLock();
 	pid = forkpty(&master_fd, NULL, NULL, NULL);
+	if (pid == 0)
+		PyOS_AfterFork();
+
 	result = _PyImport_ReleaseLock();
 	if (pid == -1)
 		return posix_error();
-	if (pid == 0)
-		PyOS_AfterFork();
 	if (result < 0) {
 		/* Don't clobber the OSError if the fork failed. */
 		PyErr_SetString(PyExc_RuntimeError,

Modified: python/branches/py3k/Python/import.c
==============================================================================
--- python/branches/py3k/Python/import.c	(original)
+++ python/branches/py3k/Python/import.c	Mon Mar  1 07:18:41 2010
@@ -295,14 +295,18 @@
 	return 1;
 }
 
-/* This function used to be called from PyOS_AfterFork to ensure that newly
-   created child processes do not share locks with the parent, but for some
-   reason only on AIX systems. Instead of re-initializing the lock, we now
-   acquire the import lock around fork() calls. */
+/* This function is called from PyOS_AfterFork to ensure that newly
+   created child processes do not share locks with the parent.
+   We now acquire the import lock around fork() calls but on some platforms
+   (Solaris 9 and earlier? see isue7242) that still left us with problems. */
 
 void
 _PyImport_ReInitLock(void)
 {
+ 	if (import_lock != NULL)
+ 		import_lock = PyThread_allocate_lock();
+ 	import_lock_thread = -1;
+ 	import_lock_level = 0;
 }
 
 #endif


More information about the Python-checkins mailing list