My process finishes its `run` function, but it doesn't die

∥☆過路亽.° 提交于 2020-01-21 18:48:50

问题


I'm subclassing multiprocessing.Process to create a class that will asynchronously grab images from a camera and push them to some queues for display and saving to disk.

The problem I'm having is that when I issue a stop command using a multiprocessing.Event object that belongs to the Process-descendant-object, the process successfully completes the last line of the run function, but then it doesn't die. The process just continues to exist and continues to return true from the is_alive function. I don't understand how this could be possible. What would cause a process to complete its run function but not die?

Maddeningly, when I separated this object from the larger context I'm using it in (which includes several other Process subclasses also running simultaneously), I can't reproduce the problem, which tends to make me think it has something to do with the rest of the code, but I don't understand how that could be - if it executed the last line of the run function, shouldn't it die regardless of what else is going on? I must be misunderstanding something about how a Process object works.

Here's the code below. When I run it, I see the message "Video acquires process STOPPED" printed out, but the process doesn't die.

class VideoAcquirer(mp.Process):
    def __init__(self, camSerial, imageQueue, monitorImageQueue, acquireSettings={}, monitorFrameRate=15):
        mp.Process.__init__(self, daemon=True)
        self.camSerial = camSerial
        self.acquireSettings = acquireSettings
        self.imageQueue = imageQueue
        self.monitorImageQueue = monitorImageQueue
        self.videoFrequencyEntry.get()Rate = monitorFrameRate
        self.stop = mp.Event()

    def stopProcess(self):
        print('Stopping video acquire process')
        self.stop.set()

    def run(self):
        system = PySpin.System.GetInstance()
        camList = system.GetCameras()
        cam = camList.GetBySerial(self.camSerial)
        cam.Init()
        nodemap = cam.GetNodeMap()
        setCameraAttributes(nodemap, self.acquireSettings)
        cam.BeginAcquisition()

        monitorFramePeriod = 1.0/self.monitorFrameRate
        print("Video monitor frame period:", monitorFramePeriod)
        lastTime = time.time()
        k = 0
        im = imp = imageResult = None
        print("Image acquisition begins now!")
        while not self.stop.is_set():
            try:
                #  Retrieve next received image
                print(1)
                imageResult = cam.GetNextImage(100) # Timeout of 100 ms to allow for stopping process
                print(2)
                #  Ensure image completion
                if imageResult.IsIncomplete():
                    print('Image incomplete with image status %d...' % imageResult.GetImageStatus())
                else:
                    #  Print image information; height and width recorded in pixels
                    width = imageResult.GetWidth()
                    height = imageResult.GetHeight()
                    k = k + 1
                    print('Grabbed Image %d, width = %d, height = %d' % (k, width, height))
                    im = imageResult.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR)
                    imp = PickleableImage(im.GetWidth(), im.GetHeight(), 0, 0, im.GetPixelFormat(), im.GetData())
                    self.imageQueue.put(imp)

                    # Put the occasional image in the monitor queue for the UI
                    thisTime = time.time()
                    if (thisTime - lastTime) >= monitorFramePeriod:
                        # print("Sent frame for monitoring")
                        self.monitorImageQueue.put((self.camSerial, imp))
                        lastTime = thisTime

                    imageResult.Release()
                print(3)
            except PySpin.SpinnakerException as ex:
                pass # Hopefully this is just because there was no image in camera buffer
                # print('Error: %s' % ex)
                # traceback.print_exc()
                # return False

        # Send stop signal to write process
        print(4)
        self.imageQueue.put(None)

        camList.Clear()
        cam.EndAcquisition()
        cam.DeInit()
        print(5)
        del cam
        system.ReleaseInstance()
        del nodemap
        del imageResult
        del im
        del imp
        del camList
        del system
        print("Video acquire process STOPPED")

I start the process from a tkinter GUI thread roughly like this:

import multiprocessing as mp
camSerial = '2318921'
queue = mp.Queue()
videoMonitorQueue = mp.Queue()
acquireSettings = [('AcquisitionMode', 'Continuous'), ('TriggerMode', 'Off'), ('TriggerSource', 'Line0'), ('TriggerMode', 'On')]

v = VideoAcquirer(camSerial, queue, videoMonitorQueue, acquireSettings=acquireSettings, monitorFrameRate=15)

And here's roughly how I stop the process, also from the tkinter GUI thread:

v.stopProcess()

Thanks for your help.

来源:https://stackoverflow.com/questions/57780333/my-process-finishes-its-run-function-but-it-doesnt-die

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!