Catching a SIGSEGV signal on an import
Chris Torek
nospam at torek.net
Tue Oct 19 04:43:21 EDT 2010
(I realize this is old but I am recovering from dental surgery and,
while on the Good Drugs for the pain, going through old stuff on
purpose :-) )
>On Thu, 09 Sep 2010 05:23:14 -0700, Ryan wrote:
>> In general, is there anyway to catch a SIGSEGV on import?
In article <pan.2010.09.09.21.20.26.16000 at nowhere.com>,
Nobody <nobody at nowhere.com> wrote:
>No. If SIGSEGV is raised, it often indicates that memory has been
>corrupted. At that point, you can't assume that the Python runtime is
>still functional.
Indeed.
Still, there *is* a way to do this, should you choose to live
somewhat dangerously.
First, make a copy of the original process. Using Unix as an
example:
pid = os.fork()
if pid == 0:
# child
import untrustworthy
os._exit(0)
The import will either succeed or fail. If it fails with a SIGSEGV
the child process will die; if not, the child will move on to the
next statement and exit (using os._exit() to bypass exit handlers,
since this is a forked child etc).
The parent can then do a waitpid and see whether the child was able
to do the import.
The obvious flaw in this method is that something that causes Python
to die with a SIGSEGV when imported probably has some serious bugs
in it, and depending on the state of the importing process, these
bugs might not cause a problem immediately, but instead set time-bombs
that will go off later. In this case, the child import will succeed
and the parent will then trust the import itself (note that you
have to re-do the same import in the parent as it is completely
independent after the fork()). Still, if you are dead set on the
idea, the test code below that I threw together here may be helpful.
-------
import os, signal, sys
pid = os.fork()
if pid == 0:
# deliberately not checking len(sys.argv) nor using try
# this allows you to see what happens if you run "python t.py"
# instead of "python t.py sig" or "python t.py fail" or
# "python t.py ok", for instance.
if sys.argv[1] == 'sig':
os.kill(os.getpid(), signal.SIGSEGV)
if sys.argv[1] == 'fail':
os._exit(1)
# Replace the above stuff with the untrustworthy "import",
# assuming you like the general idea.
os._exit(0)
print 'parent: child =', pid
wpid, status = os.waitpid(pid, 0)
print 'wpid =', wpid, 'status =', status
if os.WIFSIGNALED(status):
print 'child died from signal', os.WTERMSIG(status)
if os.WCOREDUMP(status):
print '(core dumped)'
elif os.WIFEXITED(status):
print 'child exited with', os.WEXITSTATUS(status)
# at this point the parent can repeat the "import"
else:
print 'I am confused, maybe I got the wrong pid'
-------
The same kind of thing can be done on other OSes, but all the details
will differ.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
More information about the Python-list
mailing list