On Thu, 2012-09-20 at 13:54 +0200, Jiri Moskovcak wrote:
> - doesn't work
> - the python exception are caught fine, but the file dso_list is not created
I've just tested it once more and it works on my F17 system. My test
case is adding
import subprocess;
subprocess.call("nonexisting_binary")
to the /usr/bin/phatch file followed by running phatch. This results in
a directory in /var/spool/abrt that contains the dso_list file with
python-libs package listed.
>
> On 08/15/2012 03:05 PM, Vratislav Podzimek wrote:
> > Signed-off-by: Vratislav Podzimek <[email protected]>
> > ---
> > src/hooks/abrt_exception_handler.py.in | 84
> > ++++++++++++++++++++++++++++++++--
> > 1 file changed, 80 insertions(+), 4 deletions(-)
> >
> > diff --git a/src/hooks/abrt_exception_handler.py.in
> > b/src/hooks/abrt_exception_handler.py.in
> > index 6c0659a..ecdb175 100644
> > --- a/src/hooks/abrt_exception_handler.py.in
> > +++ b/src/hooks/abrt_exception_handler.py.in
> > @@ -24,8 +24,22 @@ Module for the ABRT exception handling hook
> >
> > import sys
> > import os
> > +import inspect
> >
> > -def write_dump(tb):
> > +try:
> > + import rpm
> > + HAVE_RPM = True
> > +except ImportError as imperr:
> > + HAVE_RPM = False
> > + import syslog
> > + syslog.syslog("RPM module not available, cannot query RPM db for
> > package "\
> > + "names")
> > +
> > +class RPMinfoError(Exception):
> > + """Exception class for RPMdb-querying related errors"""
> > + pass
> > +
> > +def write_dump(tb_text, tb):
> > if sys.argv[0][0] == "/":
> > executable = os.path.abspath(sys.argv[0])
> > else:
> > @@ -33,6 +47,11 @@ def write_dump(tb):
> > # (BTW, we *can't* assume the script is in current directory.)
> > executable = sys.argv[0]
> >
> > + if HAVE_RPM:
> > + dso_list = get_dso_list(tb)
> > + else:
> > + dso_list = None
> > +
> > # Open ABRT daemon's socket and write data to it
> > try:
> > import socket
> > @@ -48,8 +67,12 @@ def write_dump(tb):
> > # This handler puts a short(er) crash descr in 1st line of
> > the backtrace.
> > # Example:
> > # CCMainWindow.py:1:<module>:ZeroDivisionError: integer
> > division or modulo by zero
> > - s.sendall("REASON=%s\0" % tb.splitlines()[0])
> > - s.sendall("BACKTRACE=%s\0" % tb)
> > + s.sendall("REASON=%s\0" % tb_text.splitlines()[0])
> > + s.sendall("BACKTRACE=%s\0" % tb_text)
> > +
> > + if dso_list:
> > + s.sendall("dso_list=%s\0" % "\n".join(dso_list))
> > +
> > s.shutdown(socket.SHUT_WR)
> >
> >
> > @@ -77,6 +100,59 @@ def write_dump(tb):
> > import syslog
> > syslog.syslog("can't communicate with ABRT daemon, is it running?
> > %s" % str(ex))
> >
> > +def get_package_for_file(fpath):
> > + """
> > + Returns package name for a given file.
> > +
> > + @param fpath: filename
> > + @type fpath: str
> > + @return: package name for the file
> > + @rtype: str
> > + @throws RPMinfoError: if package for the file cannot be found
> > +
> > + """
> > +
> > + ts = rpm.TransactionSet()
> > + mi = ts.dbMatch("basenames", fpath)
> > + try:
> > + header = mi.next()
> > + except StopIteration:
> > + raise RPMinfoError("Cannot get package and component for file "+
> > + fpath)
> > + package = "{0}-{1}-{2}.{3}".format(header["name"], header["version"],
> > + header["release"], header["arch"])
> > +
> > + return package
> > +
> > +def get_dso_list(tb):
> > + """
> > + Get the list of names of the packages whose files appear in the
> > traceback.
> > +
> > + @param tb: traceback
> > + @type tb: traceback
> > + @return: list of package names
> > + @rtype: list
> > +
> > + """
> > +
> > + if inspect.istraceback(tb):
> > + tb = inspect.getinnerframes(tb)
> > +
> > + packages = set()
> > + for (frame, fpath, lineno, func, ctx, idx) in tb:
> > + try:
> > + packages.add(get_package_for_file(fpath))
> > + except RPMinfoError as rpmerr:
> > + continue
> > +
> > + # remove the package name of the executable itself
> > + try:
> > + packages.discard(get_package_for_file(sys.argv[0]))
> > + except RPMinfoError as rpmerr:
> > + pass
> > +
> > + return list(packages)
> > +
> > def conf_enabled(var_name):
> > try:
> > file = open(@CONF_DIR@ + "/plugins/python.conf", "r")
> > @@ -187,7 +263,7 @@ def handleMyException((etype, value, tb)):
> > text += "".join(elist)
> >
> > # Send data to the daemon
> > - write_dump(text)
> > + write_dump(text, tb)
> >
> > except:
> > # Silently ignore any error in this hook,
> >
>