Python Forum

Full Version: random behavriour when handle process termination signal in Python
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello,
I have a simple code, which has random behavior when termination signal is handled. I put the question in below link, with code, but no one replied yet.
I appreciate it, if anyone can take a look and help:

https://stackoverflow.com/questions/5724...-in-python
Please do not link to another forum to ask a question.
Please show all details here.
Thank You
(Jul-30-2019, 10:31 AM)Larz60+ Wrote: [ -> ]Please do not link to another forum to ask a question.
Please show all details here.
Thank You

Ok, this is full question:
I have a simple producer/consumer python code. consumer is in main process, but for producer a class is defined, where the class makes a process for producer.

by a counter limit, main process stops the job, and terminates the producer. If termination signal is not handled, everything finish fine. but, when I added a graceful termination flag, termination signal is captured, but in a random behavior, sometimes termination is not done correctly, and I get buffer full exception (while buffer size is larger than task size). Is there any idea why this simple code has an nondeterministic behavior?

import multiprocessing
import signal
from queue import Full

buf = multiprocessing.Queue(maxsize=100)

class GracefulKiller:
    kill_now = False
    #------------------------------
    def __init__(self):
        self.kill_now = False
        for signame in [signal.SIGTERM, signal.SIGQUIT, signal.SIGINT]:
            signal.signal(signame, self.exit_tasks)     

    #------------------------------     
    def exit_tasks(self, signum, frame):
        self.kill_now = True
        process_name = multiprocessing.current_process().name   
        print("Process {} captured termination signal:{}.".format(process_name, signum,)) 

class num_source():
    prc = None
    buf2 = None
    #------------------------------------------
    def __init__(self, buf):

        self.buf2 = buf
        self.prc = multiprocessing.Process( target=self.__producer_procces__, args=(self.buf2, ))
        self.prc.daemon = True
        self.prc.start()

    #------------------------------------------
    def read_num(self):
        return self.buf2.get(block=True, timeout=60) 

    #------------------------------------------
    def terminate_request(self):
        print("Termination of process requested.")
        self.prc.terminate()
        self.prc.join(10) 
        if self.prc.is_alive():
            print("process did NOT join")
        else:
            print("process joined")

    #------------------------------------------
    def __producer_procces__(self, buf3,):  
        killer = GracefulKiller()       
        while True:
            if killer.kill_now:
                break;
            num = 123 # or a random number          
            try:
                buf3.put(num, block=True, timeout=10)
            except Full:
                print("Buffer is full, but should not!")
        return 

if __name__ == '__main__':
    src_obj = num_source(buf)
    cnt = 0
    while True:
        cnt += 1
        num = src_obj.read_num()
        print("{}-{}".format(cnt, num))
        if (cnt == 50):
            break;
    src_obj.terminate_request()