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.
........
This commit is contained in:
Gregory P. Smith 2010-03-01 06:18:41 +00:00
parent c78d79ce30
commit 24cec9fe07
4 changed files with 72 additions and 15 deletions

View file

@ -4,6 +4,7 @@ import random
from test import support from test import support
import _thread as thread import _thread as thread
import time import time
import sys
import weakref import weakref
from test import lock_tests from test import lock_tests
@ -193,8 +194,47 @@ class LockTests(lock_tests.LockTests):
locktype = thread.allocate_lock 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(): def test_main():
support.run_unittest(ThreadRunningTests, BarrierTest, LockTests) support.run_unittest(ThreadRunningTests, BarrierTest, LockTests,
TestForkInThread)
if __name__ == "__main__": if __name__ == "__main__":
test_main() test_main()

View file

@ -751,6 +751,10 @@ Extension Modules
- Expat: Fix DoS via XML document with malformed UTF-8 sequences - Expat: Fix DoS via XML document with malformed UTF-8 sequences
(CVE_2009_3560). (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 - Issue #7999: os.setreuid() and os.setregid() would refuse to accept a -1
parameter on some platforms such as OS X. parameter on some platforms such as OS X.

View file

@ -3723,14 +3723,18 @@ static PyObject *
posix_fork1(PyObject *self, PyObject *noargs) posix_fork1(PyObject *self, PyObject *noargs)
{ {
pid_t pid; pid_t pid;
int result; int result = 0;
_PyImport_AcquireLock(); _PyImport_AcquireLock();
pid = fork1(); 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) if (pid == -1)
return posix_error(); return posix_error();
if (pid == 0)
PyOS_AfterFork();
if (result < 0) { if (result < 0) {
/* Don't clobber the OSError if the fork failed. */ /* Don't clobber the OSError if the fork failed. */
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
@ -3752,14 +3756,18 @@ static PyObject *
posix_fork(PyObject *self, PyObject *noargs) posix_fork(PyObject *self, PyObject *noargs)
{ {
pid_t pid; pid_t pid;
int result; int result = 0;
_PyImport_AcquireLock(); _PyImport_AcquireLock();
pid = fork(); 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) if (pid == -1)
return posix_error(); return posix_error();
if (pid == 0)
PyOS_AfterFork();
if (result < 0) { if (result < 0) {
/* Don't clobber the OSError if the fork failed. */ /* Don't clobber the OSError if the fork failed. */
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
@ -3877,11 +3885,12 @@ posix_forkpty(PyObject *self, PyObject *noargs)
_PyImport_AcquireLock(); _PyImport_AcquireLock();
pid = forkpty(&master_fd, NULL, NULL, NULL); pid = forkpty(&master_fd, NULL, NULL, NULL);
if (pid == 0)
PyOS_AfterFork();
result = _PyImport_ReleaseLock(); result = _PyImport_ReleaseLock();
if (pid == -1) if (pid == -1)
return posix_error(); return posix_error();
if (pid == 0)
PyOS_AfterFork();
if (result < 0) { if (result < 0) {
/* Don't clobber the OSError if the fork failed. */ /* Don't clobber the OSError if the fork failed. */
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,

View file

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