This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Andre Merzky
Recipients Andre Merzky
Date 2015-08-14.02:55:38
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1439520939.88.0.252356845124.issue24862@psf.upfronthosting.co.za>
In-reply-to
Content
- create a class which is a subclass of multiprocessing.Process ('A')
 - in its __init__ create new thread ('B') and share a queue with it
 - in A's run() method, run 'C=subprocess.Popen(args="/bin/false")'
 - push 'C' though the queue to 'B'
 - call 'C.pull()' --> returns 0

Apart from returning 0, the pull will also return immediately, even if the task is long running.  The task does not die -- 'ps' shows it is well alive.

I assume that the underlying reason is that 'C' is moved sideways in the process tree, and the wait is happening in a thread which is not the parent of C.  I assume (or rather guess, really) that the system level waitpid call raises a 'ECHILD' (see wait(2)), but maybe that is misinterpreted as 'process gone'?

I append a test script which shows different combinations of process spawner and watcher classes.  All of them should report an exit code of '1' (as all run /bin/false), or should raise an error.  None should report an exit code of 0 -- but some do.

PS.: I implore you not to argue if the above setup makes sense -- it probably does not.  However, it took significant work to condense a real problem into that small excerpt, and it is not a full representation of our application stack.  I am not interested in discussing alternative approaches: we have those, and I can live with the error not being fixed.

#!/usr/bin/env python

from subprocess      import Popen
from threading       import Thread  as T
from multiprocessing import Process as P
import multiprocessing as mp

class A(P):

    def __init__(self):

        P.__init__(self)

        self.q = mp.Queue()
        def b(q):
            C = q.get()
            exit_code = C.poll()
            print "exit code: %s" % exit_code
        B = T(target = b, args=[self.q])
        B.start ()

    def run(self):
        C = Popen(args  = '/bin/false')
        self.q.put(C)

a = A()
a.start()
a.join()
History
Date User Action Args
2015-08-14 02:55:39Andre Merzkysetrecipients: + Andre Merzky
2015-08-14 02:55:39Andre Merzkysetmessageid: <1439520939.88.0.252356845124.issue24862@psf.upfronthosting.co.za>
2015-08-14 02:55:39Andre Merzkylinkissue24862 messages
2015-08-14 02:55:38Andre Merzkycreate