Blame 1001-abrt-addon-python3.patch

69165ba
From c80bc9e37c4e461033d1457f953d09f7439fea39 Mon Sep 17 00:00:00 2001
69165ba
From: Richard Marko <rmarko@redhat.com>
69165ba
Date: Tue, 18 Feb 2014 15:18:43 +0100
69165ba
Subject: [PATCH 1/2] abrt-addon-python3
69165ba
69165ba
Related to rhbz#1047085
69165ba
69165ba
Signed-off-by: Richard Marko <rmarko@redhat.com>
69165ba
69165ba
Conflicts:
69165ba
	src/hooks/Makefile.am
69165ba
---
69165ba
 src/hooks/Makefile.am                   |  19 ++-
69165ba
 src/hooks/abrt3.pth                     |   1 +
69165ba
 src/hooks/abrt_exception_handler3.py.in | 226 ++++++++++++++++++++++++++++++++
69165ba
 src/hooks/python3.conf                  |   5 +
69165ba
 4 files changed, 249 insertions(+), 2 deletions(-)
69165ba
 create mode 100644 src/hooks/abrt3.pth
69165ba
 create mode 100644 src/hooks/abrt_exception_handler3.py.in
69165ba
 create mode 100644 src/hooks/python3.conf
69165ba
69165ba
diff --git a/src/hooks/Makefile.am b/src/hooks/Makefile.am
69165ba
index 650a771..85502a0 100644
69165ba
--- a/src/hooks/Makefile.am
69165ba
+++ b/src/hooks/Makefile.am
69165ba
@@ -1,13 +1,15 @@
69165ba
 confdir = $(CONF_DIR)
69165ba
 pyhookdir = $(pyexecdir)
69165ba
+py3hookdir = $(py3execdir)
69165ba
 
69165ba
 pluginsconfdir = $(PLUGINS_CONF_DIR)
69165ba
 
69165ba
 dist_pluginsconf_DATA = \
69165ba
     CCpp.conf \
69165ba
     python.conf \
69165ba
-    vmcore.conf \
69165ba
     oops.conf
69165ba
+    python3.conf \
69165ba
+    vmcore.conf
69165ba
 
69165ba
 defaultpluginsconfdir = $(DEFAULT_PLUGINS_CONF_DIR)
69165ba
 dist_defaultpluginsconf_DATA = $(dist_pluginsconf_DATA)
69165ba
@@ -62,7 +64,12 @@ pyhook_PYTHON = \
69165ba
 	abrt_exception_handler.py \
69165ba
 	abrt.pth
69165ba
 
69165ba
+py3hook_PYTHON = \
69165ba
+	abrt_exception_handler3.py \
69165ba
+	abrt3.pth
69165ba
+
69165ba
 EXTRA_DIST = abrt_exception_handler.py.in \
69165ba
+	abrt_exception_handler3.py.in \
69165ba
 	abrt-install-ccpp-hook.in \
69165ba
 	abrt_harvest_vmcore.py.in \
69165ba
 	abrt-harvest-pstoreoops.in
69165ba
@@ -70,7 +77,7 @@ EXTRA_DIST = abrt_exception_handler.py.in \
69165ba
 CLEANFILES := $(notdir $(wildcard *~)) $(notdir $(wildcard *\#)) $(notdir $(wildcard \.\#*)) $(notdir $(wildcard *.pyc)) $(man1_MANS)
69165ba
 
69165ba
 # Generate on build
69165ba
-all: abrt_exception_handler.py
69165ba
+all: abrt_exception_handler.py abrt_exception_handler3.py
69165ba
 
69165ba
 # Must be synchronized with another sed call below.
69165ba
 abrt_exception_handler.py: abrt_exception_handler.py.in
69165ba
@@ -78,11 +85,19 @@ abrt_exception_handler.py: abrt_exception_handler.py.in
69165ba
 	    -e s,\@CONF_DIR\@,\"$(CONF_DIR)\",g \
69165ba
 	    abrt_exception_handler.py.in >abrt_exception_handler.py
69165ba
 
69165ba
+abrt_exception_handler3.py: abrt_exception_handler3.py.in
69165ba
+	sed -e s,\@VAR_RUN\@,\"$(VAR_RUN)\",g \
69165ba
+	    -e s,\@CONF_DIR\@,\"$(CONF_DIR)\",g \
69165ba
+	    abrt_exception_handler3.py.in >abrt_exception_handler3.py
69165ba
+
69165ba
 # RPM fix: we need to regenerate abrt_exception_handler.py, because it has the default ddir
69165ba
 install-data-local:
69165ba
 	sed -e s,\@VAR_RUN\@,\"$(VAR_RUN)\",g \
69165ba
 	    -e s,\@CONF_DIR\@,\"$(CONF_DIR)\",g \
69165ba
 	    abrt_exception_handler.py.in >abrt_exception_handler.py
69165ba
+	sed -e s,\@VAR_RUN\@,\"$(VAR_RUN)\",g \
69165ba
+	    -e s,\@CONF_DIR\@,\"$(CONF_DIR)\",g \
69165ba
+	    abrt_exception_handler3.py.in >abrt_exception_handler3.py
69165ba
 
69165ba
 abrt-install-ccpp-hook: abrt-install-ccpp-hook.in
69165ba
 	sed -e s,\@VAR_RUN\@,$(VAR_RUN),g \
69165ba
diff --git a/src/hooks/abrt3.pth b/src/hooks/abrt3.pth
69165ba
new file mode 100644
69165ba
index 0000000..7f75de0
69165ba
--- /dev/null
69165ba
+++ b/src/hooks/abrt3.pth
69165ba
@@ -0,0 +1 @@
69165ba
+import abrt_exception_handler3
69165ba
diff --git a/src/hooks/abrt_exception_handler3.py.in b/src/hooks/abrt_exception_handler3.py.in
69165ba
new file mode 100644
69165ba
index 0000000..b20e6f5
69165ba
--- /dev/null
69165ba
+++ b/src/hooks/abrt_exception_handler3.py.in
69165ba
@@ -0,0 +1,226 @@
69165ba
+#:mode=python:
69165ba
+# -*- coding: utf-8 -*-
69165ba
+## Copyright (C) 2014 Red Hat, Inc.
69165ba
+
69165ba
+## This program is free software; you can redistribute it and/or modify
69165ba
+## it under the terms of the GNU General Public License as published by
69165ba
+## the Free Software Foundation; either version 2 of the License, or
69165ba
+## (at your option) any later version.
69165ba
+
69165ba
+## This program is distributed in the hope that it will be useful,
69165ba
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
69165ba
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
69165ba
+## GNU General Public License for more details.
69165ba
+
69165ba
+## You should have received a copy of the GNU General Public License
69165ba
+## along with this program; if not, write to the Free Software
69165ba
+## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335  USA
69165ba
+
69165ba
+"""
69165ba
+Module for the ABRT exception handling hook
69165ba
+"""
69165ba
+
69165ba
+import sys
69165ba
+import os
69165ba
+
69165ba
+
69165ba
+def syslog(msg):
69165ba
+    """Log message to system logger (journal)"""
69165ba
+
69165ba
+    from systemd import journal
69165ba
+
69165ba
+    # required as a workaround for rhbz#1023041
69165ba
+    # where journal tries to log into non-existent log
69165ba
+    # and fails (during %check in mock)
69165ba
+    #
69165ba
+    # try/except block should be removed when the bug is fixed
69165ba
+
69165ba
+    try:
69165ba
+        journal.send(msg)
69165ba
+    except:
69165ba
+        pass
69165ba
+
69165ba
+
69165ba
+def send(data):
69165ba
+    """Send data to abrtd"""
69165ba
+
69165ba
+    response = ""
69165ba
+
69165ba
+    try:
69165ba
+        import socket
69165ba
+        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
69165ba
+        s.settimeout(5)
69165ba
+        s.connect(@VAR_RUN@ + "/abrt/abrt.socket")
69165ba
+        pre = "POST / HTTP/1.1\r\n\r\ntype=Python\0"
69165ba
+        s.sendall(pre.encode())
69165ba
+        s.sendall(data.encode())
69165ba
+
69165ba
+        s.sendall("\0".encode())
69165ba
+        s.shutdown(socket.SHUT_WR)
69165ba
+
69165ba
+        while True:
69165ba
+            buf = s.recv(256)
69165ba
+            if not buf:
69165ba
+                break
69165ba
+            response += buf.decode()
69165ba
+
69165ba
+        s.close()
69165ba
+
69165ba
+    except socket.timeout as ex:
69165ba
+        syslog("communication with ABRT daemon failed: {0}".format(ex))
69165ba
+
69165ba
+    except Exception as ex:
69165ba
+        syslog("can't communicate with ABRT daemon, is it running? {0}"
69165ba
+               .format(ex))
69165ba
+
69165ba
+    return response
69165ba
+
69165ba
+
69165ba
+def write_dump(tb_text, tb):
69165ba
+    if sys.argv[0][0] == "/":
69165ba
+        executable = os.path.abspath(sys.argv[0])
69165ba
+    else:
69165ba
+        # We don't know the path.
69165ba
+        # (BTW, we *can't* assume the script is in current directory.)
69165ba
+        executable = sys.argv[0]
69165ba
+
69165ba
+    data = "pid={0}\0".format(os.getpid())
69165ba
+    data += "executable={0}\0".format(executable)
69165ba
+    data += "reason={0}\0".format(tb_text.splitlines()[0])
69165ba
+    data += "backtrace={0}\0".format(tb_text)
69165ba
+
69165ba
+    data += "environ="
69165ba
+    for k, v in os.environ.items():
69165ba
+        data += "{0}={1}\n".format(k, v)
69165ba
+
69165ba
+    response = send(data)
69165ba
+    parts = response.split()
69165ba
+    if (len(parts) < 2
69165ba
+            or (not parts[0].startswith("HTTP/"))
69165ba
+            or (not parts[1].isdigit())
69165ba
+            or (int(parts[1]) >= 400)):
69165ba
+        syslog("error sending data to ABRT daemon: {0}".format(response))
69165ba
+
69165ba
+
69165ba
+def conf_enabled(var_name):
69165ba
+    import problem
69165ba
+    try:
69165ba
+        conf = problem.load_plugin_conf_file("python3.conf")
69165ba
+    except:
69165ba
+        return -1
69165ba
+    else:
69165ba
+        conf.get(var_name, -1)
69165ba
+
69165ba
+
69165ba
+def handle_exception(etype, value, tb):
69165ba
+    """
69165ba
+    The exception handling function.
69165ba
+
69165ba
+    progname - the name of the application
69165ba
+    version  - the version of the application
69165ba
+    """
69165ba
+
69165ba
+    try:
69165ba
+        # Restore original exception handler
69165ba
+        sys.excepthook = sys.__excepthook__  # pylint: disable-msg=E1101
69165ba
+
69165ba
+        import errno
69165ba
+
69165ba
+        # Ignore Ctrl-C
69165ba
+        # SystemExit rhbz#636913 -> this exception is not an error
69165ba
+        if etype in [KeyboardInterrupt, SystemExit]:
69165ba
+            return sys.__excepthook__(etype, value, tb)
69165ba
+
69165ba
+        # Ignore EPIPE: it happens all the time
69165ba
+        # Testcase: script.py | true, where script.py is:
69165ba
+        ## #!/usr/bin/python
69165ba
+        ## import os
69165ba
+        ## import time
69165ba
+        ## time.sleep(1)
69165ba
+        ## os.write(1, "Hello\n")  # print "Hello" wouldn't be the same
69165ba
+        #
69165ba
+        if etype == IOError or etype == OSError:
69165ba
+            if value.errno == errno.EPIPE:
69165ba
+                return sys.__excepthook__(etype, value, tb)
69165ba
+
69165ba
+        # Ignore interactive Python and similar
69165ba
+        # Check for first "-" is meant to catch "-c" which appears in this case:
69165ba
+        ## $ python -c 'import sys; print "argv0 is:%s" % sys.argv[0]'
69165ba
+        ## argv0 is:-c
69165ba
+        # Are there other cases when sys.argv[0][0] is "-"?
69165ba
+        if not sys.argv[0] or sys.argv[0][0] == "-":
69165ba
+            syslog("detected unhandled Python exception")
69165ba
+            raise Exception
69165ba
+
69165ba
+        # Ignore scripts with relative path unless "RequireAbsolutePath = no".
69165ba
+        # (In this case we can't reliably determine package)
69165ba
+        syslog("detected unhandled Python exception in '{0}'"
69165ba
+               .format(sys.argv[0]))
69165ba
+
69165ba
+        if sys.argv[0][0] != "/":
69165ba
+            if conf_enabled("RequireAbsolutePath") != 0:
69165ba
+                raise Exception
69165ba
+
69165ba
+        import traceback
69165ba
+
69165ba
+        elist = traceback.format_exception(etype, value, tb)
69165ba
+
69165ba
+        if tb is not None and etype != IndentationError:
69165ba
+            tblast = traceback.extract_tb(tb, limit=None)
69165ba
+            if len(tblast):
69165ba
+                tblast = tblast[len(tblast) - 1]
69165ba
+            extxt = traceback.format_exception_only(etype, value)
69165ba
+            if tblast and len(tblast) > 3:
69165ba
+                ll = []
69165ba
+                ll.extend(tblast[:3])
69165ba
+                ll[0] = os.path.basename(tblast[0])
69165ba
+                tblast = ll
69165ba
+
69165ba
+            text = ""
69165ba
+            for t in tblast:
69165ba
+                text += "{0}:".format(t)
69165ba
+
69165ba
+            text += "{0}\n{1}".format(extxt[0], "".join(elist))
69165ba
+
69165ba
+            trace = tb
69165ba
+            while trace.tb_next:
69165ba
+                trace = trace.tb_next
69165ba
+            frame = trace.tb_frame
69165ba
+            text += ("\nLocal variables in innermost frame:\n")
69165ba
+            try:
69165ba
+                for (key, val) in frame.f_locals.items():
69165ba
+                    text += "{0}: {1}\n".format(key, repr(val))
69165ba
+            except:
69165ba
+                pass
69165ba
+        else:
69165ba
+            text = "{0}\n\n{1}".format(value, "".join(elist))
69165ba
+
69165ba
+        # Send data to the daemon
69165ba
+        write_dump(text, tb)
69165ba
+
69165ba
+    except:
69165ba
+        # Silently ignore any error in this hook,
69165ba
+        # to not interfere with other scripts
69165ba
+        pass
69165ba
+
69165ba
+    return sys.__excepthook__(etype, value, tb)
69165ba
+
69165ba
+
69165ba
+def install_handler():
69165ba
+    """
69165ba
+    Install the exception handling function.
69165ba
+    """
69165ba
+    sys.excepthook = lambda etype, value, tb: \
69165ba
+        handle_exception(etype, value, tb)
69165ba
+
69165ba
+# install the exception handler when the abrt_exception_handler
69165ba
+# module is imported
69165ba
+try:
69165ba
+    install_handler()
69165ba
+except Exception as e:
69165ba
+    pass
69165ba
+
69165ba
+if __name__ == '__main__':
69165ba
+    # test exception raised to show the effect
69165ba
+    div0 = 1 / 0  # pylint: disable-msg=W0612
69165ba
+    sys.exit(0)
69165ba
diff --git a/src/hooks/python3.conf b/src/hooks/python3.conf
69165ba
new file mode 100644
69165ba
index 0000000..ac739a6
69165ba
--- /dev/null
69165ba
+++ b/src/hooks/python3.conf
69165ba
@@ -0,0 +1,5 @@
69165ba
+# If set to 'no', unhandled python exceptions will be caught
69165ba
+# and saved even in scripts which are run without full path
69165ba
+# in sys.argv[0].
69165ba
+# Default is 'yes': do not save them.
69165ba
+#RequireAbsolutePath = yes
69165ba
-- 
69165ba
1.8.3.1
69165ba