Search code examples
pythonpython-2.7wxpythonsignals

wxPython handling SIGTERM / SIGINT


I have a wxPython app. I want it to respond to SIGTERM and SIGINT just like as if the "close" button had been clicked. However, when I bind the signals using signal.signal(signal.SIGTERM, exit_handler), they only get executed after an event is sent to the main app graphically (clicking on a button, opening menu, etc.). How can I avoid this and execute the handles as soon as the event is caught?

Relevant parts of code:

class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        # ...
        self.Bind(wx.EVT_CLOSE, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        signal.signal(signal.SIGINT, self.signal_handler)

# ...

app = wx.App(redirect=False, clearSigInt=False)
frame = MyFrame(None, "Hello World")
app.MainLoop()

This happens even if the signal calls are moved outside any function and executed before any wx calls.


Solution

  • One way of doing it, is to add a 'timer' to fake an event.

    import wx
    import signal, os
    
    def signalUSR1_handler(sig,frame):
        print ("Signal Caught")
    
    class ExampleFrame(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, parent)
            pid_no = str(os.getpid())
            panel = wx.Panel(self)
            self.quote1 = wx.StaticText(panel, label="Test signal with timer", pos=(20, 30))
            self.quote2 = wx.StaticText(panel, label="Send this process a USR1 signal", pos=(20, 50))
            self.quote3 = wx.StaticText(panel, label="kill -s USR1 "+pid_no, pos=(20, 70))
            self.button = wx.Button(panel, -1, "Click", pos=(20,90))
            self.button.Bind(wx.EVT_BUTTON, self.OnPress)
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
            self.timer.Start(1000)
            self.Show()
        def OnPress(self, event):
            print ("Button Pressed")
        def OnTimer(self, event):
            return
    app = wx.App()
    ExampleFrame(None)
    signal.signal(signal.SIGUSR1,signalUSR1_handler)
    app.MainLoop()