在Linux下检测Python / GTK中的用户注销/关机 - 未收到SIGTERM / HUP [英] Detect user logout / shutdown in Python / GTK under Linux - SIGTERM/HUP not received

查看:201
本文介绍了在Linux下检测Python / GTK中的用户注销/关机 - 未收到SIGTERM / HUP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,这可能是一件困难的事情,我有一个pyGTK应用程序,由于X Window错误导致我无法捕捉/控制,导致随机崩溃。



所以我创建了一个包装器,一旦它检测到崩溃就重新启动应用程序,现在出现问题,当用户注销或关闭系统时,应用程序将以状态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)


从信号导入*
def clean(sig):
f = open(sig_event (sigab),
f.close()
exit(0)

for sig in(SIGABRT, ():
signal(sig,lambda * args:clean(sig))


def at():
open(SIG,SIGINT,SIGSEGV,SIGTERM) at_event,wb)

导入atexit
atexit.register(at)

f = Test()
sys.exitfunc = ex
gtk.quit_add(gtk.main_level(),foo)

gtk.main()
open(exit_event,wb)

没有其中一个成功,有没有检测系统关闭的低级方法?谷歌没有发现任何与此有关的事情。



我想一定有办法,对吗? :/ b /

编辑:
好​​的,更多的东西。

我创建了这个shell脚本:

 #!/ bin / bash 


trap test_term TERM
trap test_hup HUP


test_term(){
echoteeeeeeeeeerm>〜/ Desktop / term.info
exit 0


test_hup(){
echohuuuuuuuuuuuup>〜/ Desktop / hup.info
exit 1
}

while [true]
do
echoidle ...
sleep 2
done

还创建了一个.desktop文件来运行它:

  [桌面条目] 
Name =小猫
GenericName =小猫
Comment =小猫脚本
Exec =小猫
StartupNotify = true
终端=假
编码= UTF-8
类型=应用程序
类别=网络; GTK;
名称[de_DE] =小猫

通常这应该在注销时创建文件, hup文件已经以&开头。但不是在我的系统上。 GDM根本不关心脚本,当我重新登录时,它仍在运行。



我也尝试过使用 shopt -s huponexit



编辑2:

此处还有更多信息真正的代码,整个事情看起来像这样:

 包装脚本,捕获错误并重新启动程序
- > ;使用GTK Mainloop的主程序
- >后台更新程序线程

流程如下:

 启动Wrapper 
- >在重新启动时输入重新启动循环
<最大:
- >启动程序
- >检查返回码
- >写入错误到文件或退出包装上0

现在关机时,开始程序返回1.这意味着它要么做了hanup,要么终止了父进程,主要的问题是找出刚刚发生的这两件事中的哪一件。
X错误也会导致1。如果您想查看实际代码,请在GitHub上查看:


$ b 一个href =http://github.com/BonsaiDen/Atarashii =nofollow noreferrer> http://github.com/BonsaiDen/Atarashii


在这种情况下,你根本不能依赖信号。您必须连接到桌面会话才能获得注销即将发生的通知。

  import gnome.ui 

gnome.program_init('Program',self.version)#这会触发一个警告,即程序名已被设置两次,您可以忽略它,这似乎是最近版本的问题我们需要在这个
client.connect(')之前初始化程序,我们需要在
客户机上运行这个程序
client = gnome.ui.master_client()#将我们连接到gnome会话管理器, save-yourself',self.on_logout)#当用户确认注销/关机
client.connect('shutdown-canceled',self.on_logout_cancel)时调用#当注销/关机被取消时被调用
client.connect('die',self.on_logout)#不知道什么时候被调用,它从来没有在我的测试中得到
$ b $ def on_logout(self,* args):
#保存设置,并创建一个文件,告诉我们已经退出的包装ctly!
#我们仍然会返回状态码1,但这只是gtk崩溃了

def on_logout_cancel(self,* args):
#只要删除注销文件存在

这里一个重要的注意事项:不要试图退出 on_logout ,如果你这样做,GNOME将不会识别你的程序已经退出,并且会给你一些程序仍在运行的对话框。


OK this is presumably a hard one, I've got an pyGTK application that has random crashes due to X Window errors that I can't catch/control.

So I created a wrapper that restarts the app as soon as it detects a crash, now comes the problem, when the user logs out or shuts down the system, the app exits with status 1. But on some X errors it does so too.

So I tried literally anything to catch the shutdown/logout, with no success, here's what I've 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")

Not one of these succeeds, is there any low level way to detect the system shutdown? Google didn't find anything related to that.

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

EDIT: OK, more stuff.

I've 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 

Normally this should create the term file on logout and the hup file when it has been started with &. But not on my System. GDM doesn't care about the script at all, when I relog, it's still running.

I've also tried using shopt -s huponexit, with no success.

EDIT2:
Also here's some more information aboute the real code, the whole thing looks like this:

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

The flow is like this:

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

Now on shutdown, start program return 1. That means either it did hanup or the parent process terminated, the main problem is to figure out which of these two did just happen. X Errors result in a 1 too. Trapping in the shellscript doesn't work.

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

解决方案

OK, I finally found the solution :)

You simply can't rely on signals in this case. You have to connect to the Desktop Session in order to get notified that a logout is going to happen.

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

One important note here: Don't try to exit your program in on_logout, if you do so, GNOME won't recognize that your program has been exited and will give you the dialog that some programs are still running.

这篇关于在Linux下检测Python / GTK中的用户注销/关机 - 未收到SIGTERM / HUP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆