Search code examples
pythonpython-multiprocessingpyserialpanda3d

Exit while-looped child process when parent process is exited?


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)

Solution

  • 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.