summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_multiprocessing.py28
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_multiprocessing/multiprocessing.c34
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()
diff --git a/Misc/NEWS b/Misc/NEWS
index 9375d8f..41328fd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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;