On 03/14/2012 01:51 PM, Denys Vlasenko wrote:
This patch splits abrt-dump-oops into a generic log watcher tool,
abrt-watch-log, and oops finder, which retains the name
abrt-dump-oops.
...
Instead of running
abrt-dump-oops -rwxD /var/log/messages
about the same effect is achieved by
abrt-watch-log /var/log/messages -- abrt-dump-oops -xD
And here is the second user of abrt-watch-log: Xorg
crash analyzer:
$ abrt-dump-xorg --help
Usage: abrt-dump-xorg [-vsox] [-d DIR]/[-D] [FILE]
Extract Xorg crash from FILE (or standard input)
-v, --verbose Be verbose
-s Log to syslog
-o Print found crash data on standard output
-d DIR Create ABRT dump in DIR for every crash found
-D Same as -d DumpLocation, DumpLocation is
specified in abrt.conf
-x Make the problem directory world readable
Please review the attached patch.
--
vda
diff -x '*.po' -d -urpN abrt.2/abrt.spec.in abrt.3/abrt.spec.in
--- abrt.2/abrt.spec.in 2012-03-14 03:14:52.446107757 +0100
+++ abrt.3/abrt.spec.in 2012-03-15 02:16:27.085424033 +0100
@@ -507,6 +507,7 @@ gtk-update-icon-cache %{_datadir}/icons/
%endif
%{_bindir}/abrt-watch-log
%{_bindir}/abrt-dump-oops
+%{_bindir}/abrt-dump-xorg
%{_bindir}/abrt-action-analyze-oops
%{_mandir}/man1/abrt-action-analyze-oops.1*
diff -x '*.po' -d -urpN abrt.2/.gitignore abrt.3/.gitignore
--- abrt.2/.gitignore 2012-03-14 03:15:04.891070662 +0100
+++ abrt.3/.gitignore 2012-03-15 02:16:43.150412417 +0100
@@ -25,6 +25,7 @@ src/plugins/abrt-action-install-debuginf
src/plugins/abrt-action-trim-files
src/plugins/abrt-watch-log
src/plugins/abrt-dump-oops
+src/plugins/abrt-dump-xorg
src/plugins/abrt-dedup-client
src/plugins/abrt-retrace-client
src/plugins/abrt-action-install-debuginfo
diff -x '*.po' -d -urpN abrt.2/po/POTFILES.in abrt.3/po/POTFILES.in
--- abrt.2/po/POTFILES.in 2012-03-14 03:24:28.105323391 +0100
+++ abrt.3/po/POTFILES.in 2012-03-15 02:38:13.059137117 +0100
@@ -23,6 +23,7 @@ src/plugins/abrt-action-trim-files.c
src/plugins/abrt-dedup-client.c
src/plugins/abrt-watch-log.c
src/plugins/abrt-dump-oops.c
+src/plugins/abrt-dump-xorg.c
src/plugins/abrt-retrace-client.c
src/plugins/analyze_LocalGDB.xml.in
src/plugins/analyze_RetraceServer.xml.in
diff -x '*.po' -d -urpN abrt.2/src/plugins/abrt-dump-oops.c abrt.3/src/plugins/abrt-dump-oops.c
--- abrt.2/src/plugins/abrt-dump-oops.c 2012-03-14 21:53:33.350848696 +0100
+++ abrt.3/src/plugins/abrt-dump-oops.c 2012-03-15 02:34:30.514389890 +0100
@@ -206,9 +206,6 @@ int main(int argc, char **argv)
};
unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
- if ((opts & OPT_d) && (opts & OPT_D))
- show_usage_and_die(program_usage_string, program_options);
-
export_abrt_envvars(0);
msg_prefix = g_progname;
@@ -218,6 +215,16 @@ int main(int argc, char **argv)
logmode = LOGMODE_SYSLOG;
}
+ if (opts & OPT_D)
+ {
+ if (opts & OPT_d)
+ show_usage_and_die(program_usage_string, program_options);
+ load_abrt_conf();
+ debug_dumps_dir = g_settings_dump_location;
+ g_settings_dump_location = NULL;
+ free_abrt_conf_data();
+ }
+
argv += optind;
if (argv[0])
xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);
@@ -267,9 +274,6 @@ int main(int argc, char **argv)
"Reported %u kernel oopses to Abrt",
oops_cnt
);
-
- //if (opts & OPT_D)
- // free_abrt_conf_data();
}
}
//list_free_with_free(oops_list);
diff -x '*.po' -d -urpN abrt.2/src/plugins/abrt-dump-xorg.c abrt.3/src/plugins/abrt-dump-xorg.c
--- abrt.2/src/plugins/abrt-dump-xorg.c 1970-01-01 01:00:00.000000000 +0100
+++ abrt.3/src/plugins/abrt-dump-xorg.c 2012-03-15 02:34:30.514389890 +0100
@@ -0,0 +1,240 @@
+/*
+ Copyright (C) 2012 ABRT Team
+ Copyright (C) 2012 Red Hat, 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 <syslog.h>
+#include "libabrt.h"
+
+/* I want to use -Werror, but gcc-4.4 throws a curveball:
+ * "warning: ignoring return value of 'ftruncate', declared with attribute warn_unused_result"
+ * and (void) cast is not enough to shut it up! Oh God...
+ */
+#define IGNORE_RESULT(func_call) do { if (func_call) /* nothing */; } while (0)
+
+enum {
+ OPT_v = 1 << 0,
+ OPT_s = 1 << 1,
+ OPT_o = 1 << 2,
+ OPT_d = 1 << 3,
+ OPT_D = 1 << 4,
+ OPT_x = 1 << 5,
+};
+
+static unsigned g_opts;
+static const char *debug_dumps_dir = ".";
+static unsigned dir_seq_no = 0;
+
+static char *skip_pfx(char *p)
+{
+ if (p[0] != '[')
+ return p;
+ char *q = strchr(p, ']');
+ if (!q)
+ return p;
+ if (q[1] == ' ')
+ return q + 2;
+ return p;
+}
+
+static char *list2lines(GList *list)
+{
+ struct strbuf *s = strbuf_new();
+ while (list)
+ {
+ strbuf_append_str(s, (char*)list->data);
+ strbuf_append_char(s, '\n');
+ free(list->data);
+ list = g_list_delete_link(list, list);
+ }
+ return strbuf_free_nobuf(s);
+}
+
+static void save_bt_to_dump_dir(const char *bt, const char *reason)
+{
+ time_t t = time(NULL);
+ const char *iso_date = iso_date_string(&t);
+ /* dump should be readable by all if we're run with -x */
+ uid_t my_euid = (uid_t)-1L;
+ mode_t mode = 0644;
+ /* and readable only for the owner otherwise */
+ if (!(g_opts & OPT_x))
+ {
+ mode = 0640;
+ my_euid = geteuid();
+ }
+
+ pid_t my_pid = getpid();
+
+ struct dump_dir *dd;
+ {
+ char base[sizeof("xorg-YYYY-MM-DD-hh:mm:ss-%lu-%lu") + 2 * sizeof(long)*3];
+ sprintf(base, "xorg-%s-%lu-%u", iso_date, (long)my_pid, ++dir_seq_no);
+ char *path = concat_path_file(debug_dumps_dir, base);
+ dd = dd_create(path, /*uid:*/ my_euid, mode);
+ free(path);
+ }
+
+ if (dd)
+ {
+ dd_create_basic_files(dd, /*uid:*/ my_euid);
+ dd_save_text(dd, "abrt_version", VERSION);
+ dd_save_text(dd, FILENAME_ANALYZER, "xorg");
+ dd_save_text(dd, FILENAME_REASON, reason);
+ dd_save_text(dd, FILENAME_BACKTRACE, bt);
+ dd_close(dd);
+ }
+}
+
+/* Called after "Backtrace:" line was read.
+ * Example (yes, stray newline before 'B' is real):
+[ 86985.879]<space>
+Backtrace:
+[ 86985.880] 0: /usr/bin/Xorg (xorg_backtrace+0x2f) [0x462d8f]
+[ 86985.880] 1: /usr/bin/Xorg (0x400000+0x67b56) [0x467b56]
+[ 86985.880] 2: /lib64/libpthread.so.0 (0x30a5800000+0xf4f0) [0x30a580f4f0]
+[ 86985.880] 3: /usr/lib64/xorg/modules/extensions/librecord.so (0x7ff6c225e000+0x26c3) [0x7ff6c22606c3]
+[ 86985.880] 4: /usr/bin/Xorg (_CallCallbacks+0x3c) [0x43820c]
+[ 86985.880] 5: /usr/bin/Xorg (WriteToClient+0x1f5) [0x466315]
+[ 86985.880] 6: /usr/lib64/xorg/modules/extensions/libdri2.so (ProcDRI2WaitMSCReply+0x4f) [0x7ff6c1e4feef]
+[ 86985.880] 7: /usr/lib64/xorg/modules/extensions/libdri2.so (DRI2WaitMSCComplete+0x52) [0x7ff6c1e4e6d2]
+[ 86985.880] 8: /usr/lib64/xorg/modules/drivers/intel_drv.so (0x7ff6c1bfb000+0x25ae4) [0x7ff6c1c20ae4]
+[ 86985.880] 9: /usr/lib64/libdrm.so.2 (drmHandleEvent+0xa3) [0x376b407513]
+[ 86985.880] 10: /usr/bin/Xorg (WakeupHandler+0x6b) [0x4379db]
+[ 86985.880] 11: /usr/bin/Xorg (WaitForSomething+0x1a9) [0x460289]
+[ 86985.880] 12: /usr/bin/Xorg (0x400000+0x3379a) [0x43379a]
+[ 86985.880] 13: /usr/bin/Xorg (0x400000+0x22dc5) [0x422dc5]
+[ 86985.880] 14: /lib64/libc.so.6 (__libc_start_main+0xed) [0x30a542169d]
+[ 86985.880] 15: /usr/bin/Xorg (0x400000+0x230b1) [0x4230b1]
+[ 86985.880] Segmentation fault at address 0x7ff6bf09e010
+ */
+static void process_xorg_bt(void)
+{
+ char *reason = NULL;
+ GList *list = NULL;
+ unsigned cnt = 0;
+ char *line;
+ while ((line = xmalloc_fgetline(stdin)) != NULL)
+ {
+ char *p = skip_pfx(line);
+
+ if (*p < '0' || *p > '9')
+ {
+ if (strncasecmp(p, "Segmentation fault", strlen("Segmentation fault")) == 0)
+ {
+ overlapping_strcpy(line, p);
+ reason = line;
+ line = NULL;
+ }
+ /* TODO: Other cases when we have useful reason string? */
+ break;
+ }
+
+ errno = 0;
+ char *end;
+ IGNORE_RESULT(strtoul(p, &end, 10));
+ if (errno || end == p || *end != ':')
+ break;
+
+ /* This looks like bt line. Save it to list */
+ overlapping_strcpy(line, p);
+ list = g_list_prepend(list, line);
+ line = NULL;
+ if (++cnt > 255) /* prevent ridiculously large bts */
+ break;
+ }
+ free(line);
+
+ if (list)
+ {
+ list = g_list_reverse(list);
+ char *bt = list2lines(list); /* frees list */
+ if (g_opts & OPT_o)
+ printf("%s%s%s", bt, reason ? reason : "", reason ? "\n" : "");
+ if (g_opts & (OPT_d|OPT_D))
+ save_bt_to_dump_dir(bt, reason ? reason : "Xorg server crashed");
+ free(bt);
+ }
+ free(reason);
+}
+
+int main(int argc, char **argv)
+{
+ /* I18n */
+ setlocale(LC_ALL, "");
+#if ENABLE_NLS
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
+
+ abrt_init(argv);
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ "& [-vsox] [-d DIR]/[-D] [FILE]\n"
+ "\n"
+ "Extract Xorg crash from FILE (or standard input)"
+ );
+ /* Keep OPT_z enums and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_BOOL( 's', NULL, NULL, _("Log to syslog")),
+ OPT_BOOL( 'o', NULL, NULL, _("Print found crash data on standard output")),
+ OPT_STRING('d', NULL, &debug_dumps_dir, "DIR", _("Create ABRT dump in DIR for every crash found")),
+ OPT_BOOL( 'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
+ OPT_BOOL( 'x', NULL, NULL, _("Make the problem directory world readable")),
+ OPT_END()
+ };
+ unsigned opts = g_opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+ export_abrt_envvars(0);
+
+ msg_prefix = g_progname;
+ if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
+ {
+ openlog(msg_prefix, 0, LOG_DAEMON);
+ logmode = LOGMODE_SYSLOG;
+ }
+
+ if (opts & OPT_D)
+ {
+ if (opts & OPT_d)
+ show_usage_and_die(program_usage_string, program_options);
+ load_abrt_conf();
+ debug_dumps_dir = g_settings_dump_location;
+ g_settings_dump_location = NULL;
+ free_abrt_conf_data();
+ }
+
+ argv += optind;
+ if (argv[0])
+ xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);
+
+ char *line;
+ while ((line = xmalloc_fgetline(stdin)) != NULL)
+ {
+ char *p = skip_pfx(line);
+ if (strcmp(p, "Backtrace:") == 0)
+ {
+ free(line);
+ process_xorg_bt();
+ continue;
+ }
+ free(line);
+ }
+
+ return 0;
+}
diff -x '*.po' -d -urpN abrt.2/src/plugins/Makefile.am abrt.3/src/plugins/Makefile.am
--- abrt.2/src/plugins/Makefile.am 2012-03-14 03:14:31.418176392 +0100
+++ abrt.3/src/plugins/Makefile.am 2012-03-15 02:18:02.839346242 +0100
@@ -9,6 +9,7 @@ bin_SCRIPTS = \
bin_PROGRAMS = \
abrt-watch-log \
abrt-dump-oops \
+ abrt-dump-xorg \
abrt-action-analyze-c \
abrt-action-analyze-python \
abrt-action-analyze-oops \
@@ -97,6 +98,20 @@ abrt_dump_oops_LDADD = \
$(GLIB_LIBS) \
$(LIBREPORT_LIBS) \
../lib/libabrt.la
+
+abrt_dump_xorg_SOURCES = \
+ abrt-dump-xorg.c
+abrt_dump_xorg_CPPFLAGS = \
+ -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ $(GLIB_CFLAGS) \
+ $(LIBREPORT_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Wwrite-strings -Werror
+abrt_dump_xorg_LDADD = \
+ $(GLIB_LIBS) \
+ $(LIBREPORT_LIBS) \
+ ../lib/libabrt.la
abrt_action_analyze_c_SOURCES = \
abrt-action-analyze-c.c