summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2009-10-22 16:08:57 +0200
committerJiri Moskovcak <jmoskovc@redhat.com>2009-10-22 16:08:57 +0200
commit67492995a84e88403bfbe5a46627d53dd99e7711 (patch)
tree57701ad3379abb5530a032fd4c4a2baa41d47a68
parent038b9a3473f56dcf80cf5eb053f8cefcc0ef5f01 (diff)
parent828288e948ccc6c5c1525eaf44bc8cb83960e9f1 (diff)
downloadabrt-67492995a84e88403bfbe5a46627d53dd99e7711.tar.gz
abrt-67492995a84e88403bfbe5a46627d53dd99e7711.tar.xz
abrt-67492995a84e88403bfbe5a46627d53dd99e7711.zip
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
-rw-r--r--.gitignore1
-rw-r--r--abrt.spec1
-rw-r--r--lib/Plugins/CCpp.cpp83
-rw-r--r--src/CLI/Makefile.am2
-rw-r--r--src/Hooks/Makefile.am18
-rw-r--r--src/Hooks/abrt-pyhook-helper.cpp138
-rw-r--r--src/Hooks/abrt_exception_handler.py.in53
-rw-r--r--src/Hooks/sitecustomize.py12
8 files changed, 264 insertions, 44 deletions
diff --git a/.gitignore b/.gitignore
index f92001af..ce402b3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,4 +45,5 @@ src/Daemon/abrtd
src/Hooks/abrt_exception_handler.py
src/Hooks/dumpoops
src/Hooks/hookCCpp
+src/Hooks/abrt-pyhook-helper
stamp-h1
diff --git a/abrt.spec b/abrt.spec
index 72be3e44..51f72bb2 100644
--- a/abrt.spec
+++ b/abrt.spec
@@ -346,6 +346,7 @@ fi
%files addon-python
%defattr(-,root,root,-)
+%{_bindir}/%{name}-pyhook-helper
%config(noreplace) %{_sysconfdir}/%{name}/pyhook.conf
%{python_sitearch}/ABRTUtils.so
%{_libdir}/%{name}/libPython.so*
diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp
index 0e0eb3b3..f79877e6 100644
--- a/lib/Plugins/CCpp.cpp
+++ b/lib/Plugins/CCpp.cpp
@@ -156,6 +156,89 @@ static pid_t ExecVP(char** pArgs, uid_t uid, std::string& pOutput)
return 0;
}
+enum LineRating
+{
+ /* RATING -- EXAMPLE */
+ MissingEverything = 0, // #0 0x0000dead in ?? ()
+ MissingFunction = 1, // #0 0x0000dead in ?? () from /usr/lib/libfoobar.so.4
+ MissingLibrary = 2, // #0 0x0000dead in foobar()
+ MissingSourceFile = 3, // #0 0x0000dead in FooBar::FooBar () from /usr/lib/libfoobar.so.4
+ Good = 4, // #0 0x0000dead in FooBar::crash (this=0x0) at /home/user/foobar.cpp:204
+ InvalidRating = -1 // (dummy invalid value)
+};
+
+static const LineRating BestRating = Good;
+
+LineRating rate_line(std::string line)
+{
+ bool function = false;
+ bool library = false;
+ bool source_file = false;
+
+#define FOUND(x) (line.find(x) != std::string::npos)
+ if (FOUND(" in ") && !FOUND(" in ??"))
+ function = true;
+
+ if (FOUND(" from "))
+ library = true;
+
+ if(FOUND(" at "))
+ source_file = true;
+#undef FOUND
+
+ /* see the "enum LineRating" comments for possible combinations */
+ if (function && source_file)
+ return Good;
+ if (function && library)
+ return MissingSourceFile;
+ if (function)
+ return MissingLibrary;
+ if (library)
+ return MissingFunction;
+
+ return MissingEverything;
+}
+
+/* returns number of "stars" to show*/
+int rate_backtrace(std::string backtrace)
+{
+ int l = backtrace.length();
+ int i;
+ std::string s = "";
+ int multiplier = 0;
+ int rating = 0;
+ int best_possible_rating = 0;
+
+ /*we get the lines from the end, b/c of the rating multiplier
+ which gives weight to the first lines*/
+ for (i=l-1; i>=0; i--)
+ {
+ if (backtrace[i] == '#') /*this divides frames from each other*/
+ {
+ multiplier++;
+ rating += rate_line(s) * multiplier;
+ best_possible_rating += BestRating * multiplier;
+
+ s = ""; /*starting new line*/
+ } else
+ {
+ s=backtrace[i]+s;
+ }
+ }
+
+ /*returning number of "stars" to show*/
+ if (rating >= best_possible_rating*0.8)
+ return 4;
+ if (rating >= best_possible_rating*0.6)
+ return 3;
+ if (rating >= best_possible_rating*0.4)
+ return 2;
+ if (rating >= best_possible_rating*0.2)
+ return 1;
+
+ return 0;
+}
+
static void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktrace)
{
update_client(_("Getting backtrace..."));
diff --git a/src/CLI/Makefile.am b/src/CLI/Makefile.am
index 7b10bfb8..dbeb1c38 100644
--- a/src/CLI/Makefile.am
+++ b/src/CLI/Makefile.am
@@ -27,6 +27,6 @@ man_MANS = abrt-cli.1
EXTRA_DIST = $(man_MANS)
completiondir = $(sysconfdir)/bash_completion.d
-completion_DATA = abrt-cli.bash
+dist_completion_DATA = abrt-cli.bash
DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am
index be1b1a2f..4eb25e2d 100644
--- a/src/Hooks/Makefile.am
+++ b/src/Hooks/Makefile.am
@@ -1,5 +1,5 @@
libexec_PROGRAMS = hookCCpp
-bin_PROGRAMS = dumpoops
+bin_PROGRAMS = dumpoops abrt-pyhook-helper
# CCpp
hookCCpp_SOURCES = \
@@ -29,6 +29,18 @@ dumpoops_CPPFLAGS = \
dumpoops_LDADD = \
../../lib/Utils/libABRTUtils.la
+# abrt-pyhook-helper
+abrt_pyhook_helper_SOURCES = \
+ abrt-pyhook-helper.cpp
+abrt_pyhook_helper_CPPFLAGS = \
+ -I$(srcdir)/../../inc \
+ -I$(srcdir)/../../lib/Utils \
+ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
+ -DVAR_RUN=\"$(VAR_RUN)\" \
+ -D_GNU_SOURCE
+abrt_pyhook_helper_LDADD = \
+ ../../lib/Utils/libABRTUtils.la
+
man_MANS = pyhook.conf.5
python_PYTHON = sitecustomize.py abrt_exception_handler.py
@@ -45,3 +57,7 @@ abrt_exception_handler.py:
# RPM fix: we need to regenerate abrt_exception_handler.py, because it has the default ddir
install-data-local:
sed s,@DEBUG_DUMP_DIR@,$(DEBUG_DUMPS_DIR),g abrt_exception_handler.py.in > abrt_exception_handler.py
+
+install-data-hook:
+ chmod u+s,g+s $(DESTDIR)$(bindir)/abrt-pyhook-helper
+
diff --git a/src/Hooks/abrt-pyhook-helper.cpp b/src/Hooks/abrt-pyhook-helper.cpp
new file mode 100644
index 00000000..4ac6ada6
--- /dev/null
+++ b/src/Hooks/abrt-pyhook-helper.cpp
@@ -0,0 +1,138 @@
+/*
+ python-hook-writer.cpp - writes data to the /var/cache/abrt directory
+ with SUID bit
+
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <argp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "DebugDump.h"
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+const char *argp_program_version = "abrt-pyhook-helper " VERSION;
+const char *argp_program_bug_address = "<crash-catcher@lists.fedorahosted.org>";
+
+static char doc[] = "abrt-pyhook-helper -- stores crash data to abrt shared directory";
+
+static struct argp_option options[] = {
+ {"pid" , 'p', "PID" , 0, "PID of process that caused the crash" },
+ {"executable", 'e', "PATH" , 0, "absolute path to the program that crashed" },
+ {"uuid" , 'u', "UUID" , 0, "hash generated from the backtrace"},
+ {"cmdline" , 'c', "TEXT" , 0, "command line of the crashed program"},
+ {"loginuid" , 'l', "UID" , 0, "login UID"},
+ { 0 }
+};
+
+struct arguments
+{
+ char *pid;
+ char *executable;
+ char *uuid;
+ char *cmdline;
+ char *loginuid;
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ /* Get the input argument from argp_parse, which we
+ know is a pointer to our arguments structure. */
+ struct arguments *arguments = (struct arguments*)state->input;
+
+ switch (key)
+ {
+ case 'p': arguments->pid = arg; break;
+ case 'e': arguments->executable = arg; break;
+ case 'u': arguments->uuid = arg; break;
+ case 'c': arguments->cmdline = arg; break;
+ case 'l': arguments->loginuid = arg; break;
+
+ case ARGP_KEY_ARG:
+ argp_usage(state);
+ exit(1);
+ break;
+
+ case ARGP_KEY_END:
+ if (!arguments->pid)
+ {
+ argp_usage(state);
+ exit(1);
+ }
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+/* Our argp parser. */
+static struct argp argp = { options, parse_opt, 0, doc };
+
+int main(int argc, char** argv)
+{
+ struct arguments arguments;
+ argp_parse (&argp, argc, argv, 0, 0, &arguments);
+
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "%s/pyhook-%ld-%s", DEBUG_DUMPS_DIR,
+ (long)time(NULL), arguments.pid);
+
+ CDebugDump dd;
+ dd.Create(path, geteuid());
+ dd.SaveText(FILENAME_ANALYZER, "Python");
+ if (arguments.executable)
+ dd.SaveText(FILENAME_EXECUTABLE, arguments.executable);
+ if (arguments.cmdline)
+ dd.SaveText("cmdline", arguments.cmdline);
+ if (arguments.uuid)
+ dd.SaveText("uuid", arguments.uuid);
+ if (arguments.loginuid)
+ dd.SaveText("uid", arguments.loginuid);
+
+ // Read the backtrace from stdin.
+ int c;
+ int capacity = 1024;
+ char *bt = (char*)malloc(capacity);
+ char *btptr = bt;
+ while ((c = getchar()) != EOF)
+ {
+ if (c >= 0 && c <= 255)
+ *btptr++ = (char)c;
+ if (btptr - bt >= capacity - 1)
+ {
+ capacity *= 2;
+ bt = (char*)realloc(bt, capacity);
+ if (!bt)
+ {
+ printf("Error while allocating memory for backtrace.");
+ return 1;
+ }
+ }
+ }
+ *btptr = '\0';
+
+ dd.SaveText("backtrace", bt);
+ free(bt);
+ dd.Close();
+
+ return 0;
+}
diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in
index 8ac7aa23..362aaf24 100644
--- a/src/Hooks/abrt_exception_handler.py.in
+++ b/src/Hooks/abrt_exception_handler.py.in
@@ -45,10 +45,10 @@ def exception_function():
import sys
import os
import syslog
+import subprocess
# abrt lib for saving debugdumps
import ABRTUtils
-
__DUMPHASH = {}
# FIXME: do length limits on obj dumps.
def __dump_class(instance, fd, level=0):
@@ -105,45 +105,20 @@ def __dump_class(instance, fd, level=0):
fd.write("%s%s: %s\n" % (pad, key, value))
def write_dump(pid, tb_uuid, tb):
- import time
- ttime = int(time.time())
- # localstatedir
- dir_name = "@DEBUG_DUMP_DIR@/pyhook-%s-%s" % (ttime, pid)
- dd = ABRTUtils.CDebugDump()
- try:
- #os.mkdir(dir_name)
- dd.Create(dir_name, os.getuid())
- except Exception, e:
- syslog.syslog("abrt: Cannot create dir %s %s" % (dir_name, e))
- return
- # save executable
- fexecutable = open("%s/executable" % dir_name, "w")
+ executable = "Exception raised from python shell"
if sys.argv[0]:
- fexecutable.write(os.path.abspath(sys.argv[0]))
- else:
- fexecutable.write("Exception raised from python shell")
- fexecutable.close()
- # save coredump
- coredump = open("%s/backtrace" % dir_name, "w")
- coredump.write(tb)
- coredump.close()
- # save uuid
- uuid = open("%s/uuid" % dir_name, "w")
- uuid.write(tb_uuid)
- uuid.close()
- # save cmdline
- cmdline = open("%s/cmdline" % dir_name, "w")
- cmdline.write(open("/proc/%s/cmdline" % pid).read().replace('\x00',' '))
- cmdline.close()
- # save uid
- uid = open("%s/uid" % dir_name, "w")
- uid.write(open("/proc/%s/loginuid" % pid).readlines()[0])
- uid.close()
- # save analyzer
- analyzer = open("%s/analyzer" % dir_name, "w")
- analyzer.write("Python")
- analyzer.close()
- dd.Close()
+ executable = os.path.abspath(sys.argv[0])
+
+ command = ["abrt-pyhook-helper"]
+ command.append("--pid=%s" % pid)
+ command.append("--executable=%s" % executable)
+ command.append("--uuid=%s" % tb_uuid)
+ command.append("--cmdline=%s" % open("/proc/%s/cmdline" % pid).read().replace('\x00',' '))
+ command.append("--loginuid=%s" % open("/proc/%s/loginuid" % pid).readlines()[0])
+
+ helper = subprocess.Popen(command, stdin=subprocess.PIPE)
+ helper.communicate(tb)
+ helper.wait()
def __dump_exception(out, text, tracebk):
'write a traceback to "out"'
diff --git a/src/Hooks/sitecustomize.py b/src/Hooks/sitecustomize.py
index 56c6669b..32a3747b 100644
--- a/src/Hooks/sitecustomize.py
+++ b/src/Hooks/sitecustomize.py
@@ -1,14 +1,16 @@
+# ABRT crash hook
+#
# This special script is placed in
# /usr/local/lib/pythonNNN/site-packages/sitecustomize.py
# and python interpreter runs it automatically everytime
-# some python script is executed
+# some python script is executed.
config = None
conf = {}
try:
config = open("/etc/abrt/pyhook.conf","r")
except:
- #silently ignore if file doesn't exist
+ # Silently ignore if file doesn't exist.
pass
try:
@@ -20,10 +22,14 @@ try:
line = config.readline().lower().replace(' ','').strip('\n').split('=')
conf[line[0]] = line[1]
except:
- # ignore silently everything, because we don't want to bother user if this hook doesn't work
+ # Ignore silently everything, because we don't want to bother user
+ # if this hook doesn't work.
pass
if conf.has_key("enabled"):
+ # Prevent abrt exception handler from running when the abrtd daemon is
+ # not active.
+ # abrtd sets the value to "no" when deactivated and vice versa.
if conf["enabled"] == "yes":
try:
from abrt_exception_handler import *