Catching a SIGSEGV signal on an import

Discussion in 'Python' started by Ryan, Sep 9, 2010.

  1. Ryan

    Ryan Guest

    Is there anyway to catch a SIGSEGV signal that results from an import?
    I'd like to get a list of all modules on the sys.path. The module
    pkgutil has a nice method, walk_packages, to do just that. But, there
    is a third party extension that throws a SIGSEGV when imported. I
    tried to create a signal handler with the signal module like:


    #!/bin/env python
    import pkgutil
    import signal
    import traceback

    def handler(signal, stackframe):
    raise ImportError

    # Handle seg faults that may occur during an import
    signal.signal(signal.SIGSEGV, handler)

    if __name__ == "__main__":
    goodMods = []

    def onerror(pkgName):
    sys.stdout.write('Unable to import package %s\n' % pkgName)
    traceback.print_exc(file=sys.stdout)
    sys.stdout.write('\n')
    #sys.stdout.flush()

    for importer, mod, ispkg in pkgutil.walk_packages(path=None,
    onerror=onerror):
    goodMods.append(mod)

    for m in goodMods:
    sys.stdout.write(m + '\n')
    sys.stdout.flush()

    This sometimes works. But, since SIGSEGV is asynchronous it is not
    guaranteed to work all the time. In general, is there anyway to catch
    a SIGSEGV on import? If so, is there a way to use that with
    pkgutil.walk_packages to get all the modules on sys.path?

    Thanks,
    Ryan
     
    Ryan, Sep 9, 2010
    #1
    1. Advertising

  2. Ryan

    Nobody Guest

    On Thu, 09 Sep 2010 05:23:14 -0700, Ryan wrote:

    > But, since SIGSEGV is asynchronous


    SIGSEGV is almost always synchronous.

    > In general, is there anyway to catch a SIGSEGV on import?


    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.

    In general, even attempting to catch it is a bad idea. Particularly in a
    high-level language; getting it right in C is hard enough.
     
    Nobody, Sep 9, 2010
    #2
    1. Advertising

  3. Ryan

    Chris Torek Guest

    (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 <>,
    Nobody <> 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
     
    Chris Torek, Oct 19, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Frank
    Replies:
    0
    Views:
    2,148
    Frank
    Aug 5, 2003
  2. Signal handler for SIGSEGV.

    , Dec 30, 2005, in forum: C Programming
    Replies:
    13
    Views:
    949
  3. stuffduff
    Replies:
    1
    Views:
    397
    stuffduff
    Jun 20, 2007
  4. Replies:
    1
    Views:
    626
    Ioannis Gyftos
    Dec 20, 2007
  5. Lance Pollard

    Catching "File Saved" or CMD-W Signal?

    Lance Pollard, Sep 19, 2009, in forum: Ruby
    Replies:
    2
    Views:
    139
    Lance Pollard
    Sep 19, 2009
Loading...

Share This Page