Repository: nipy/nipype

Issue:
Apparent multiprocessing API change in Python 3.7
### Summary

There's a Python 3.7 failure that just began exhibiting on Travis.

```Python
[gw0] [ 99%] FAILED pipeline/plugins/test/test_legacymultiproc_nondaemon.py::test_run_multiproc_nondaemon_true
...
=================================== FAILURES ===================================
______________________ test_run_multiproc_nondaemon_true _______________________
[gw0] linux -- Python 3.7.1 /home/travis/virtualenv/python3.7.1/bin/python
    def test_run_multiproc_nondaemon_true():
        # with nondaemon_flag = True, the execution should succeed
>       result = run_multiproc_nondaemon_with_flag(True)
/home/travis/build/nipy/nipype/nipype/pipeline/plugins/tests/test_legacymultiproc_nondaemon.py:165: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/travis/build/nipy/nipype/nipype/pipeline/plugins/tests/test_legacymultiproc_nondaemon.py:132: in run_multiproc_nondaemon_with_flag
    'non_daemon': nondaemon_flag
/home/travis/build/nipy/nipype/nipype/pipeline/engine/workflows.py:579: in run
    runner = plugin_mod(plugin_args=plugin_args)
/home/travis/build/nipy/nipype/nipype/pipeline/plugins/legacymultiproc.py:162: in __init__
    initargs=(self._cwd,)
/opt/python/3.7.1/lib/python3.7/multiprocessing/pool.py:177: in __init__
    self._repopulate_pool()
/opt/python/3.7.1/lib/python3.7/multiprocessing/pool.py:238: in _repopulate_pool
    self._wrap_exception)
/opt/python/3.7.1/lib/python3.7/multiprocessing/pool.py:252: in _repopulate_pool_static
    wrap_exception)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <[AttributeError("'NonDaemonProcess' object has no attribute '_closed'") raised in repr()] NonDaemonProcess object at 0x7fa0ad3d24a8>
group = <multiprocessing.context.ForkContext object at 0x7fa0d7aeda90>
target = <function worker at 0x7fa0af430840>, name = None
args = (<multiprocessing.queues.SimpleQueue object at 0x7fa0ad2afcf8>, <multiprocessing.queues.SimpleQueue object at 0x7fa0ad10d6a0>, <built-in function chdir>, ('/tmp/test_engine_y5eb4eh0',), 10, True)
kwargs = {}
    def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
                 *, daemon=None):
>       assert group is None, 'group argument must be None for now'
E       AssertionError: group argument must be None for now
/opt/python/3.7.1/lib/python3.7/multiprocessing/process.py:74: AssertionError
```

### Platform details:

```
Python: 3.7
INSTALL_DEB_DEPENDECIES=true NIPYPE_EXTRAS="doc,tests,nipy,profiler" CI_SKIP_TEST=1
```
### Execution environment

Travis



Discussion:

Resolving patch:
diff --git a/nipype/pipeline/plugins/legacymultiproc.py b/nipype/pipeline/plugins/legacymultiproc.py
--- a/nipype/pipeline/plugins/legacymultiproc.py
+++ b/nipype/pipeline/plugins/legacymultiproc.py
@@ -11,7 +11,7 @@
 
 # Import packages
 import os
-from multiprocessing import Process, Pool, cpu_count, pool
+from multiprocessing import Pool, cpu_count, pool
 from traceback import format_exception
 import sys
 from logging import INFO
@@ -74,23 +74,23 @@ def run_node(node, updatehash, taskid):
     return result
 
 
-class NonDaemonProcess(Process):
-    """A non-daemon process to support internal multiprocessing.
-    """
-
-    def _get_daemon(self):
-        return False
-
-    def _set_daemon(self, value):
-        pass
-
-    daemon = property(_get_daemon, _set_daemon)
-
-
 class NonDaemonPool(pool.Pool):
     """A process pool with non-daemon processes.
     """
-    Process = NonDaemonProcess
+    def Process(self, *args, **kwds):
+        proc = super(NonDaemonPool, self).Process(*args, **kwds)
+
+        class NonDaemonProcess(proc.__class__):
+            """Monkey-patch process to ensure it is never daemonized"""
+            @property
+            def daemon(self):
+                return False
+
+            @daemon.setter
+            def daemon(self, val):
+                pass
+        proc.__class__ = NonDaemonProcess
+        return proc
 
 
 class LegacyMultiProcPlugin(DistributedPluginBase):


Test patch: