Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signal handler inside a class

Tags:

python

signals

I am trying to write a class to handle signals using the signal python module. The reason for having a class is to avoid the use of globals. This is the code I came up with, but unfortunately it is not working:

import signal
import constants


class SignalHandler (object):
    def __init__(self):        
        self.counter = 0
        self.break = False
        self.vmeHandlerInstalled = False

    def setVmeHandler(self):        
        self.vmeBufferFile = open('/dev/vme_shared_memory0', 'rb')
        self.vmeHandlerInstalled = True

        signal.signal(signal.SIGUSR1, self.traceHandler)
        signal.siginterrupt(signal.SIGUSR1, False)
        #...some other stuff...


    def setBreakHandler(self):
        signal.signal(signal.SIGINT, self.newBreakHandler)
        signal.siginterrupt(signal.SIGINT, False)

    def newBreakHandler(self, signum, frame):        
        self.removeVMEHandler()
        self.break = True

    def traceHandler(self, signum, frame):
        self.counter += constants.Count        

    def removeVMEHandler(self):    
        if not self.vmeHandlerInstalled: return
        if self.vmeBufferFile is None: return

        signal.signal(signal.SIGUSR1, signal.SIG_DFL)

        self.vmeHandlerInstalled = False

On the main program I use this class in the following way:

def run():
    sigHandler = SignalHandler()

    sigHandler.setBreakHandler()
    sigHandler.setVmeHandler()

    while not sigHandler.break:
        #....do some stuff
        if sigHandler.counter >= constants.Count:
            #...do some stuff

This solution is not working, as it appears that the handler for the signal.SIGUSR1 installed in the setVmeHandler method never gets called.

So my question is: is it possible to handle signal inside a class or shall I use globals?

like image 766
toti08 Avatar asked Jan 14 '16 09:01

toti08


2 Answers

I got a similar problem as toti08, referring to setVmeHandler(self), and found out the handler must have matching parameters i.e. (self, signum,frame).

like image 88
tkingless Avatar answered Sep 27 '22 18:09

tkingless


To answer your question, I created the following simple code:

import signal
import time


class ABC(object):
    def setup(self):
        signal.signal(signal.SIGUSR1, self.catch)
        signal.siginterrupt(signal.SIGUSR1, False)

    def catch(self, signum, frame):
        print("xxxx", self, signum, frame)


abc = ABC()
abc.setup()
time.sleep(20)

If I run it:

python ./test.py

Then in another window send a USR1 signal:

kill -USR1 4357

The process prints the expected message:

('xxxx', <__main__.ABC object at 0x7fada09c6190>, 10, <frame object at 0x7fada0aaf050>)

So I think the answer is Yes, it possible to handle signal inside a class.

As for why you code doesn't work, sorry, I have no idea.

like image 29
Penguin Brian Avatar answered Sep 27 '22 17:09

Penguin Brian