0

I have a script that instantiates a number of objects from other classes. When the calling script ends, these objects need to do some cleanup work, especially the closing and deleting of some tempfiles.

I've experimented with a number of ways to trigger the cleanup, and a number of them work when the calling script ends nicely...but none of them work in the event the calling script crashes or ends unexpectedly (like due to an uncaught error).

Is it possible to get the "child objects" (if that's the right term) to run their cleanup in the case of a crash or unexpected error?

Here's some test scripts...

THE OBJECT CLASS WHICH GETS CALLED...

import signal
import atexit
import os

class testme(object):
    def __init__(self):
        self.var = 1
        self.sigs()
        atexit.register(self.close)


    def __enter__(self):
        print "Hit enter"

    def sigs(self):
        for i in [x for x in dir(signal) if x.startswith("SIG")]:
          try:
            print "setting signal ", str(i)
            signum = getattr(signal,i)
            signal.signal(signum,self.close)
          except Exception, e:
            print ("Skipping " + str(i) + " in set_signal_handler")

    def __del__(self):
        print "Hit del"
        self.close()

    def __exit__(self, exception_type, exception_value, traceback):
        print "Hit exit"
        self.close()

    def close(self):
        print "Closing"
        # Perform cleanup actions here
        # Especially closing and deleting temp files

(The different signals that the "sigs()" function is [hopefully] setting is at the end of this post)

test2.py

import time
import testme
import sys

if __name__ == "__main__":
    with testme.testme() as obj:
        time.sleep(30)
        sys.exit()

test3.py

import time
import testme
import sys

if __name__ == "__main__":
    obj = testme.testme()
    time.sleep(30)
    sys.exit()

If I run test2.py and let it finish normally I get the following...

setting signal  SIGABRT
setting signal  SIGALRM
[...snip...]
Skipping SIG_DFL in set_signal_handler
setting signal  SIG_IGN
Hit enter
Hit exit
Closing
Closing
Hit del
Closing

If I run test2.py and use "kill -9" to end it (crash) I get...

setting signal  SIGABRT
[...snip...]
setting signal  SIG_IGN
Hit enter

If I run test3.py and let it finish, I get...

setting signal  SIGABRT
[...snip...]
setting signal  SIG_IGN
Closing
Hit del
Closing

If I run test3.py and use "kill -9" on it, I get the following...

setting signal  SIGABRT
[...snip...]
setting signal  SIG_IGN

(in other words...nothing)

EDIT: I did find that uncaught exceptions in the calling script do allow the del() in the child objects to run. Still wondering if there's a way to cleanly close out the child objects on other failures.

SIGNALS THAT (I hope) ARE GETTING SET BY sigs()...

setting signal  SIGABRT
setting signal  SIGALRM
setting signal  SIGBUS
setting signal  SIGCHLD
setting signal  SIGCLD
setting signal  SIGCONT
setting signal  SIGFPE
setting signal  SIGHUP
setting signal  SIGILL
setting signal  SIGINT
setting signal  SIGIO
setting signal  SIGIOT
setting signal  SIGKILL
Skipping SIGKILL in set_signal_handler
setting signal  SIGPIPE
setting signal  SIGPOLL
setting signal  SIGPROF
setting signal  SIGPWR
setting signal  SIGQUIT
setting signal  SIGRTMAX
setting signal  SIGRTMIN
setting signal  SIGSEGV
setting signal  SIGSTOP
Skipping SIGSTOP in set_signal_handler
setting signal  SIGSYS
setting signal  SIGTERM
setting signal  SIGTRAP
setting signal  SIGTSTP
setting signal  SIGTTIN
setting signal  SIGTTOU
setting signal  SIGURG
setting signal  SIGUSR1
setting signal  SIGUSR2
setting signal  SIGVTALRM
setting signal  SIGWINCH
setting signal  SIGXCPU
setting signal  SIGXFSZ
setting signal  SIG_DFL
Skipping SIG_DFL in set_signal_handler
setting signal  SIG_IGN    
4

1 回答 1

2

好吧,您的问题是kill -9,又名 SIGKILL,其设计无法被捕获。对于犯罪过程,这是一个保证的暴力死亡。

命令 kill 将指定的信号发送到指定的进程或进程组。如果未指定信号,则发送 TERM 信号。TERM 信号将杀死未捕获此信号的进程。 对于其他进程,可能需要使用 KILL (9) 信号,因为无法捕获此信号。

为了atexit正常工作,它需要能够捕捉到一些信号。您可以尝试发送kill -15(SIGTERM)。

于 2014-12-20T23:39:12.530 回答