2010-03-22 1 views
5

확인 이것은 아마도 어려운 일입니다. 나는 잡을 수없는 X 창 오류로 인해 임의의 충돌이있는 pyGTK 응용 프로그램을 가지고 있습니다. /제어.Linux에서 Python/GTK로 사용자 로그 아웃/종료 감지 - SIGTERM/HUP 수신하지 않음

그래서 충돌을 감지하자마자 앱을 다시 시작하는 래퍼를 만들었습니다. 사용자가 시스템을 로그 아웃하거나 시스템을 종료하면 상태 1로 종료됩니다.하지만 일부 X 오류 너무합니다.

그래서 내가 더 성공, 종료/로그 아웃을 잡기 위해 문자 그대로 아무것도 시도, 여기에 내가 무엇을 시도했다입니다 :하지

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") 

이 성공의 한 시스템을 감지 할 수있는 낮은 수준의 방법이있다 일시 휴업? Google은 관련 정보를 찾지 못했습니다.

나는 방법이 있어야한다고 생각하는데, 맞습니까? :/

편집 : 확인, 더 많은 것들.

나는이 쉘 스크립트를 만들었습니다

#!/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 

을 또한 실행하기의 .desktop 파일을 만든 :

[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 

는 일반적으로이 로그 아웃에 대한 용어 파일과 HUP 파일을 작성해야합니다 &으로 시작했을 때. 하지만 제 시스템에는 없습니다. GDM은 스크립트를 전혀 신경 쓰지 않습니다. 다시 relog하면 여전히 실행 중입니다.

shopt -s huponexit도 사용해 보았습니다. 성공하지 못했습니다.

는 EDIT2 :
또한 여기에 실제 코드 aboute 좀 더 많은 정보가있어, 전부는 다음과 같습니다

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

흐름이 같다 : 종료에 지금

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

, start program return 1. 이것은 hanup 또는 부모 프로세스가 종료되었음을 의미합니다. 주된 문제는이 두 프로세스 중 어느 것이 발생했는지 파악하는 것입니다. X 오류도 1이됩니다. 셸 스크립트에서 트래핑이 작동하지 않습니다.

당신이 실제 코드를 살펴하려면

는 GitHub의에서 이상을 체크 아웃 :
http://github.com/BonsaiDen/Atarashii

답변

1

OK, 나는 마침내 해결책 :

당신은 단순히이 경우 신호에 의존하지 수를 발견했다. 로그 아웃이 발생한다는 알림을 받으려면 데스크톱 세션에 연결해야합니다.

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's just gtk crashing somehow 

def on_logout_cancel(self, *args): 
    # simply delete the logout file if it exists 

여기서 한 가지 중요한 참고 : 이렇게하면, 그놈은 프로그램이 종료 된 것을 인식하지 못합니다 및 일부 프로그램은 여전히 ​​것을 당신에게 대화 상자를 제공합니다 on_logout에 프로그램을 종료하지 마십시오 달리는.

0

당신은 GTK의 이벤트 루프를 닫습니다 잊어 버렸습니다.창을 닫을 때

이 코드는 코드 0와 함께 종료 :

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() 

편집 :

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) 

의 나머지 : 다음은 SIGTERM 신호를 잡을 수있는 코드이다 코드는 위와 동일하며 변경이 없습니다. 그것은 SIGTERM을 파이썬 프로세스에 보낼 때 여기에서 작동합니다. gtk main 루프가 끝나고 프로그램이 종료 코드 0으로 종료됩니다.

+0

그래도 문제가 해결되지 않으면 사용자가 로그 아웃하거나 시스템을 종료 할 때 destroy_event가 호출되지 않고 위의 파일 중 하나도 생성되지 않습니다. 다른 문제는 래퍼 스크립트로 인한 것입니다. 먼저 "kill"상태가되므로 부모 프로세스가 없어져서 앱이 종료됩니다. –

+0

추가 연구에 따르면 실제로 프로세스는 SIGTERM을 가져야합니다. 그러나 그것은 하나를 얻지 못했고, 단지 죽임을당하는 것 같습니다 ... –

+0

GDM의 소스에 따르면 처음에는 SIGTERM을 보냅니다, 파이썬은 신경 쓰지 않는 것 같습니다 :/ –