User exit / shutdown detection in Python / GTK under Linux - SIGTERM / HUP not received

OK, this seems to be complicated, I have a pyGTK application that has random crashes due to X Window errors that I cannot catch / control.

So, I created a shell that restarts the application as soon as it detects a failure, now there is a problem when the user logs out or shuts down the system, the application exits with status 1. But on some errors X does this too.

So, I literally literally tried to catch a shutdown / logout, without success, this is what I tried:

import pygtk import gtk import sys class Test(gtk.Window): def delete_event(self, widget, event, data=None): open("delete_event", "wb") def destroy_event(self, widget, data=None): open("destroy_event", "wb") def destroy_event2(self, widget, event, data=None): open("destroy_event2", "wb") def __init__(self): gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) self.show() self.connect("delete_event", self.delete_event) self.connect("destroy", self.destroy_event) self.connect("destroy-event", self.destroy_event2) def foo(): open("add_event", "wb") def ex(): open("sys_event", "wb") from signal import * def clean(sig): f = open("sig_event", "wb") f.write(str(sig)) f.close() exit(0) for sig in (SIGABRT, SIGILL, SIGINT, SIGSEGV, SIGTERM): signal(sig, lambda *args: clean(sig)) def at(): open("at_event", "wb") import atexit atexit.register(at) f = Test() sys.exitfunc = ex gtk.quit_add(gtk.main_level(), foo) gtk.main() open("exit_event", "wb") 

None of these options work, is there a low-level way to detect system shutdown? Google did not find anything related to this.

I think there must be a way, am I right?: /

EDIT: Alright, more stuff.

I created this shell script:

 #!/bin/bash trap test_term TERM trap test_hup HUP test_term(){ echo "teeeeeeeeeerm" >~/Desktop/term.info exit 0 } test_hup(){ echo "huuuuuuuuuuup" >~/Desktop/hup.info exit 1 } while [ true ] do echo "idle..." sleep 2 done 

And also created a .desktop file to run it:

 [Desktop Entry] Name=Kittens GenericName=Kittens Comment=Kitten Script Exec=kittens StartupNotify=true Terminal=false Encoding=UTF-8 Type=Application Categories=Network;GTK; Name[de_DE]=Kittens 

Usually this should create a term file at logout and a hup file when it was launched with &. But not in my System. GDM doesn't care about the script at all, when I reboot, it still works.

I also tried using shopt -s huponexit , without any success.

EDIT2:
Also here is additional information about the real code, it all looks like this:

 Wrapper Script, that catches errors and restarts the programm -> Main Programm with GTK Mainloop -> Background Updater Thread 

The stream is as follows:

 Start Wrapper -> enter restart loop while restarts < max: -> start program -> check return code -> write error to file or exit the wrapper on 0 

Now, at the end of work, start program return 1. This means that it is either hanup or the parent process is complete, the main problem is to find out which of the two has occurred. X Errors also lead to 1. The trap in shellscript does not work.

If you want to take a look at the actual code, check it out on GitHub:
http://github.com/BonsaiDen/Atarashii

+6
python linux gtk pygtk sigterm
source share
2 answers

OK, I finally found a solution :)

In this case, you simply cannot rely on signals. You need to connect to a desktop session to receive a notification about logging out.

 import gnome.ui gnome.program_init('Program', self.version) # This is going to trigger a warning that program name has been set twice, you can ignore this, it seems to be a problem with a recent version of glib, the warning is all over the place out there client = gnome.ui.master_client() # connect us to gnome session manager, we need to init the program before this client.connect('save-yourself', self.on_logout) # This gets called when the user confirms the logout/shutdown client.connect('shutdown-cancelled', self.on_logout_cancel) # This gets called when the logout/shutdown is canceled client.connect('die', self.on_logout) # Don't know when this gets called it never got in my tests def on_logout(self, *args): # save settings an create a file that tells the wrapper that we have exited correctly! # we'll still return with status code 1, but that just gtk crashing somehow def on_logout_cancel(self, *args): # simply delete the logout file if it exists 

Important note: do not try to exit the program on_logout , if you do this, GNOME will not know that your program has exited, and you will see a dialog on_logout stating that some programs are still running.

+2
source share

You forgot to close the gtk event loop.

This code exits with code 0 when the window closes:

 import gtk class Test(gtk.Window): def destroy_event(self, widget, data=None): gtk.main_quit() def __init__(self): gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) self.connect("destroy", self.destroy_event) self.show() f = Test() gtk.main() 

EDIT: Here is the code to catch the SIGTERM signal:

 import signal def handler(signum, frame): print 'Signal handler called with signal', signum print 'Finalizing main loop' gtk.main_quit() signal.signal(signal.SIGTERM, handler) 

The rest of the code is exactly the same as above, no changes. It works here when I send SIGTERM to a python process: end of main gtk loop and program exits with exit code 0 .

0
source share

All Articles