diff options
-rw-r--r-- | Lib/test/test_multiprocessing.py | 28 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Modules/_multiprocessing/multiprocessing.c | 34 |
3 files changed, 51 insertions, 14 deletions
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 935e224..c2a2f19 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -264,6 +264,7 @@ class _TestProcess(BaseTestCase): p = self.Process(target=time.sleep, args=(DELTA,)) self.assertNotIn(p, self.active_children()) + p.daemon = True p.start() self.assertIn(p, self.active_children()) @@ -334,6 +335,7 @@ class _TestSubclassingProcess(BaseTestCase): def test_subclassing(self): uppercaser = _UpperCaser() + uppercaser.daemon = True uppercaser.start() self.assertEqual(uppercaser.submit('hello'), 'HELLO') self.assertEqual(uppercaser.submit('world'), 'WORLD') @@ -512,6 +514,7 @@ class _TestQueue(BaseTestCase): # fork process p = self.Process(target=self._test_fork, args=(queue,)) + p.daemon = True p.start() # check that all expected items are in the queue @@ -552,6 +555,7 @@ class _TestQueue(BaseTestCase): for i in xrange(4)] for p in workers: + p.daemon = True p.start() for i in xrange(10): @@ -816,7 +820,9 @@ class _TestEvent(BaseTestCase): #self.assertEqual(event.is_set(), False) - self.Process(target=self._test_event, args=(event,)).start() + p = self.Process(target=self._test_event, args=(event,)) + p.daemon = True + p.start() self.assertEqual(wait(), True) # @@ -856,6 +862,7 @@ class _TestValue(BaseTestCase): self.assertEqual(sv.value, cv[1]) proc = self.Process(target=self._test, args=(values,)) + proc.daemon = True proc.start() proc.join() @@ -919,6 +926,7 @@ class _TestArray(BaseTestCase): self.f(seq) p = self.Process(target=self.f, args=(arr,)) + p.daemon = True p.start() p.join() @@ -1285,6 +1293,7 @@ class _TestRemoteManager(BaseTestCase): manager.start() p = self.Process(target=self._putter, args=(manager.address, authkey)) + p.daemon = True p.start() manager2 = QueueManager2( @@ -1326,6 +1335,7 @@ class _TestManagerRestart(BaseTestCase): manager.start() p = self.Process(target=self._putter, args=(manager.address, authkey)) + p.daemon = True p.start() queue = manager.get_queue() self.assertEqual(queue.get(), 'hello world') @@ -1449,6 +1459,7 @@ class _TestConnection(BaseTestCase): conn, child_conn = self.Pipe() p = self.Process(target=self._echo, args=(child_conn,)) + p.daemon = True p.start() child_conn.close() # this might complete before child initializes @@ -1521,6 +1532,7 @@ class _TestConnection(BaseTestCase): conn, child_conn = self.Pipe(duplex=True) p = self.Process(target=self._writefd, args=(child_conn, b"foo")) + p.daemon = True p.start() with open(test_support.TESTFN, "wb") as f: fd = f.fileno() @@ -1544,6 +1556,7 @@ class _TestConnection(BaseTestCase): conn, child_conn = self.Pipe(duplex=True) p = self.Process(target=self._writefd, args=(child_conn, b"bar", True)) + p.daemon = True p.start() with open(test_support.TESTFN, "wb") as f: fd = f.fileno() @@ -1632,11 +1645,13 @@ class _TestPicklingConnections(BaseTestCase): lconn, lconn0 = self.Pipe() lp = self.Process(target=self._listener, args=(lconn0, families)) + lp.daemon = True lp.start() lconn0.close() rconn, rconn0 = self.Pipe() rp = self.Process(target=self._remote, args=(rconn0,)) + rp.daemon = True rp.start() rconn0.close() @@ -1774,6 +1789,7 @@ class _TestSharedCTypes(BaseTestCase): string.value = latin('hello') p = self.Process(target=self._double, args=(x, y, foo, arr, string)) + p.daemon = True p.start() p.join() @@ -1846,6 +1862,7 @@ class _TestFinalize(BaseTestCase): conn, child_conn = self.Pipe() p = self.Process(target=self._test_finalize, args=(child_conn,)) + p.daemon = True p.start() p.join() @@ -1915,12 +1932,16 @@ class _TestLogging(BaseTestCase): reader, writer = multiprocessing.Pipe(duplex=False) logger.setLevel(LEVEL1) - self.Process(target=self._test_level, args=(writer,)).start() + p = self.Process(target=self._test_level, args=(writer,)) + p.daemon = True + p.start() self.assertEqual(LEVEL1, reader.recv()) logger.setLevel(logging.NOTSET) root_logger.setLevel(LEVEL2) - self.Process(target=self._test_level, args=(writer,)).start() + p = self.Process(target=self._test_level, args=(writer,)) + p.daemon = True + p.start() self.assertEqual(LEVEL2, reader.recv()) root_logger.setLevel(root_level) @@ -2106,6 +2127,7 @@ def _ThisSubProcess(q): def _TestProcess(q): queue = multiprocessing.Queue() subProc = multiprocessing.Process(target=_ThisSubProcess, args=(queue,)) + subProc.daemon = True subProc.start() subProc.join() @@ -192,6 +192,9 @@ Library Extension Modules ----------------- +- Issue #12950: Fix passing file descriptors in multiprocessing, under + OpenIndiana/Illumos. + - Issue #12764: Fix a crash in ctypes when the name of a Structure field is not a string. diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c index 5b23fc3..7582664 100644 --- a/Modules/_multiprocessing/multiprocessing.c +++ b/Modules/_multiprocessing/multiprocessing.c @@ -97,31 +97,37 @@ ProcessingCtrlHandler(DWORD dwCtrlType) /* Functions for transferring file descriptors between processes. Reimplements some of the functionality of the fdcred module at http://www.mca-ltd.com/resources/fdcred_1.tgz. */ +/* Based in http://resin.csoft.net/cgi-bin/man.cgi?section=3&topic=CMSG_DATA */ static PyObject * multiprocessing_sendfd(PyObject *self, PyObject *args) { int conn, fd, res; - char dummy_char; - char buf[CMSG_SPACE(sizeof(int))]; - struct msghdr msg = {0}; struct iovec dummy_iov; + char dummy_char; + struct msghdr msg; struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + unsigned char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; if (!PyArg_ParseTuple(args, "ii", &conn, &fd)) return NULL; dummy_iov.iov_base = &dummy_char; dummy_iov.iov_len = 1; - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = &cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); msg.msg_iov = &dummy_iov; msg.msg_iovlen = 1; + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - msg.msg_controllen = cmsg->cmsg_len; * (int *) CMSG_DATA(cmsg) = fd; Py_BEGIN_ALLOW_THREADS @@ -138,20 +144,26 @@ multiprocessing_recvfd(PyObject *self, PyObject *args) { int conn, fd, res; char dummy_char; - char buf[CMSG_SPACE(sizeof(int))]; - struct msghdr msg = {0}; struct iovec dummy_iov; + struct msghdr msg = {0}; struct cmsghdr *cmsg; + union { + struct cmsghdr hdr; + unsigned char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; if (!PyArg_ParseTuple(args, "i", &conn)) return NULL; dummy_iov.iov_base = &dummy_char; dummy_iov.iov_len = 1; - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = &cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); msg.msg_iov = &dummy_iov; msg.msg_iovlen = 1; + cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; |