|
|
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 |
|