1

I'm trying to close child process(which is doing while loop) when parent process is exited (Whenever parent process is clean-exit, forced-exit or exited because of exception) not to make child process a zombie process.

I'm making a game that communicates with Arduino (using serial), and main process is running Panda3D's ShowBase instance(Game engine, do render and another many things) so main must not be stopped.
So, I created subprocess using multiprocessing module so that main process is safe from stopping to wait serial in.

But the problem is, when i close Panda3D window, call sys.exit() or exited because of exception, main process exits immediately, and can't join or give false to subprocess, so subprocess becomes zombie.

I have no idea how to solve this. What should i do to make it work as i expected?

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from multiprocessing import Process, Queue
from panda3d.core import *

class HW_support:
    def hardware_event_handler(self, process_status):
        self.process_alive = True
        while self.process_alive:
            print('Working!')
            self.process_alive = process_status.get()
        return

if __name__ == '__main__':
    from direct.showbase.ShowBase import ShowBase
    import sys
    class TestApp(ShowBase):
        def __init__(self):
            ShowBase.__init__(self)
            self.process_status_argv = Queue()
            self.HW_sub_process = Process(target = HW_support().hardware_event_handler, args=(self.process_status_argv,))
            self.HW_sub_process.start()
            base.messenger.toggleVerbose()
            taskMgr.add(self.task_make_alive, 'task_make_alive')

            base.accept('escape', self.exit_taskloop)
        def exit_taskloop(self, task=None):
            taskMgr.stop()

        def task_make_alive(self, task=None):
            self.process_status_argv.put(True)
            return task.cont

    app = TestApp()
    app.run()
    #app.HW_sub_process.join()
    app.process_status_argv.put(False)
martineau
  • 119,623
  • 25
  • 170
  • 301
Lee M.U.
  • 123
  • 1
  • 12

2 Answers2

1

Multiple processes makes things a lot more complicated.

To shut down the HW_support process cleanly, you need to send it the message via your Queue object, then the parent needs to join() it (wait for it to exit) before exiting itself.

Anything that could make the parent exit unexpectedly (console interrupt, thrown exception, sys.exit, etc etc) will need to be carefully caught and managed so that you can still cleanly shut down the child before exiting.

Bill Gribble
  • 1,797
  • 12
  • 15
  • Umm...then is it a good idea to add function to subprocess that investigates main process is alive and if it's dead, exit itself? I'm also considering not to use multiprocessing, but i don't have no idea either :-P – Lee M.U. Nov 03 '16 at 18:43
  • 2
    Another answer suggests using a file for that purpose, which could work. An older question (http://stackoverflow.com/questions/25542110/kill-child-process-if-parent-is-killed-in-python) has some good tips, including setting the child to 'daemon mode' which will cause it to be killed when the parent is killed. – Bill Gribble Nov 03 '16 at 18:49
  • Oh, that way has a value of experiment. I'll try that way later, though solution that uses a file works great :-) Anyway, Thanks for answering! – Lee M.U. Nov 03 '16 at 19:01
  • setting it to daemon is really probably the right answer :P I think ... lol not sure why i didnt think of that – Joran Beasley Nov 03 '16 at 19:07
  • I just tried this and working seamless! Setting subprocess as demon is also a nice and cool idea. – Lee M.U. Nov 03 '16 at 19:21
1

in the main program add this at the top (well below import multiprocessing)

if multiprocessing.current_process().name == 'MainProcess':
    import atexit
    atexit.register(lambda *a : os.remove("running.txt"))
    open("running.txt","wb").close()

in the subprocces change your while True loop to while os.path.exists("running.txt"):

alternatively you could have atexit place a message in the queue or do whatever to signal to the subprocess that it should exit.

Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • This is very interesting idea...i'll try it right now, Thanks! – Lee M.U. Nov 03 '16 at 18:44
  • 1
    note that as the block at the top i think `if __name__ == "__main__"` would work also ... I just wanted it to be very clear what the purpose of the if block was – Joran Beasley Nov 03 '16 at 18:51
  • This works! And as you said, placing it in if __name__ == "__main__" would be better.(for JUST IN CASE) Anyway, Thanks bro! – Lee M.U. Nov 03 '16 at 18:56