I have one module which uses python "threading" for concurrency, and "signal" for shutdown hook:
signal.signal(signal.SIGINT, self.shutdownhook)
I have another module which uses dbus and gobject
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
....
GObject.threads_init()
mainloop = GObject.MainLoop()
mainloop.run()
When I run them seperately, they both operate as expected and ctrl+c
causes termination via "KeyboardInterrupt".
However, when I run them together the mainloop terminates but the shutdown hook is never called - the process does not terminate without kill -9 pid
.
Can someone please explain why this occurs, and how best to integrate the two models
Here is a working example which highlights my problem. I cannot exit the program with just a CTRL+C and the shutdown hook is not called in this case either.
import threading
import signal
import sys
from gi.repository import GObject
def runMainloop():
print('running mainloop')
mainloop.run()
def shutdown():
print('shutdown')
def readInput():
print('readInput')
print(sys.stdin.readline())
if __name__ == '__main__':
signal.signal(signal.SIGINT, shutdown)
signal.signal(signal.SIGTERM, shutdown)
GObject.threads_init()
mainloop = GObject.MainLoop()
mainloopThread = threading.Thread(name='mainloop', target=runMainloop)
mainloopThread.setDaemon(True)
mainloopThread.start()
print('started')
inputThread = threading.Thread(name='input', target=readInput)
inputThread.start()
print('started input')
No one is interested, so let me try.
Just to be on the same page:
import signal
from gi.repository import GObject
GObject.threads_init()
mainloop = GObject.MainLoop()
signal.signal(signal.SIGINT, lambda n, f: mainloop.quit())
mainloop.run()
This code works:
import signal
from gi.repository import GObject
signal.signal(signal.SIGINT, lambda n, f: print("kill"))
GObject.threads_init()
mainloop = GObject.MainLoop()
mainloop.run()
I've first registered signal handler, and then initiated the loop. Strange is that it is not called. However result is - as expected...
As a side note - according to their doc... mainloop
is deprecated. That is first thing.
Here is example with reading from stdin
inside MainLoop
:
import signal
import sys
from gi.repository import GObject, GLib
GObject.threads_init()
def readInput():
print('readInput\n')
while True:
input = sys.stdin.readline()
print(input)
if input.strip() == 'exit':
print('closing main loop')
mainloop.quit()
print('terminating thread')
return
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_DFL)
mainloop = GObject.MainLoop.new(None, False)
GObject.timeout_add(1000, readInput)
# inputThread = threading.Thread(name='input', target=readInput)
# inputThread.start()
# print('started input')
print('running mainloop\n')
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
Adding .new(None, False)
allows CTRL-C
working normally. Took it from here, also here is another thread about integrating pulse audio controller with GLib
/GObject
loop. There are samples about integration dbus with the loop, but I'm not sure which way you wish to go...
Adding a timer makes the loop receive Unix signals.
import gi
from gi.repository import GLib
import signal
GLib.threads_init()
mainloop = GLib.MainLoop()
signal.signal(signal.SIGTERM, lambda signum, frame: mainloop.quit())
GLib.timeout_add(1000, lambda *args: (print("tick") or True))
try:
mainloop.run()
except KeyboardInterrupt:
print()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With