On Wed, 2010-10-13 at 13:26 +0200, Denys Vlasenko wrote:
On Wed, 2010-10-13 at 12:15 +0200, Denys Vlasenko wrote:
> This patch splits off uuid generation for CCpp
> to a separate program:
>
> # abrt-action-analyze-c --help
> Usage: abrt-action-analyze-c [-v] -d DIR
>
> Calculates and saves UUID
>
> -v, --verbose be verbose
> -d DIR Crash dump directory
>
> Run tested.
>
> Thus, now entire cycle of coredump processing/reporting
> consists of external programs:
>
> abrt-action-analyze-c
> abrt-action-save-package-data
> abrt-action-install-debuginfo
> abrt-action-generate-backtrace
> abrt-action-bugzilla
>
> Please review.
Found a bug on python side, here is an updated patch.
Gosh, I sent an old one again. THIS is the real updated one.
--
vda
diff -x '*.po' -d -urpN abrt.6/abrt.spec abrt.7/abrt.spec
--- abrt.6/abrt.spec 2010-10-11 19:32:47.000000000 +0200
+++ abrt.7/abrt.spec 2010-10-13 11:39:50.702237887 +0200
@@ -349,6 +349,7 @@ fi
%endif
%{_sbindir}/abrtd
%{_sbindir}/abrt-server
+%{_sbindir}/abrt-action-analyze-c
%{_sbindir}/abrt-action-generate-backtrace
%{_sbindir}/abrt-action-save-package-data
%{_bindir}/abrt-action-bugzilla
diff -x '*.po' -d -urpN abrt.6/inc/crash_types.h abrt.7/inc/crash_types.h
--- abrt.6/inc/crash_types.h 2010-10-11 19:31:22.000000000 +0200
+++ abrt.7/inc/crash_types.h 2010-10-13 11:58:57.947436353 +0200
@@ -62,8 +62,9 @@
// dump directory is created before its DB entry, and DB has to learn
// CD_UID from _somewhere_ in order to be able to store it in DB record,
// right?)
-#define CD_UID "uid" /* lowercase: compat with older versions */
-#define CD_UUID "UUID"
+#define CD_UID "uid"
+/* CCpp is converted to save uuid as a file (python and oops aren't yet): */
+#define CD_UUID "uuid"
#define CD_INFORMALL "InformAll"
#define CD_DUMPDIR "DumpDir"
#define CD_COUNT "Count"
diff -x '*.po' -d -urpN abrt.6/lib/plugins/CCpp.cpp abrt.7/lib/plugins/CCpp.cpp
--- abrt.6/lib/plugins/CCpp.cpp 2010-10-13 12:08:09.422437249 +0200
+++ abrt.7/lib/plugins/CCpp.cpp 2010-10-13 12:42:23.818579540 +0200
@@ -75,78 +75,6 @@ static void create_hash(char hash_str[SH
//log("hash2:%s str:'%s'", hash_str, pInput);
}
-/**
- *
- * @param[out] status See `man 2 wait` for status information.
- * @return Malloc'ed string
- */
-static char* exec_vp(char **args, uid_t uid, int redirect_stderr, unsigned timeout_sec,
int *status)
-{
- /* Nuke everything which may make setlocale() switch to non-POSIX locale:
- * we need to avoid having gdb output in some obscure language.
- */
- static const char *const unsetenv_vec[] = {
- "LANG",
- "LC_ALL",
- "LC_COLLATE",
- "LC_CTYPE",
- "LC_MESSAGES",
- "LC_MONETARY",
- "LC_NUMERIC",
- "LC_TIME",
- NULL
- };
-
- int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID |
EXECFLG_QUIET;
- if (redirect_stderr)
- flags |= EXECFLG_ERR2OUT;
- VERB1 flags &= ~EXECFLG_QUIET;
-
- int pipeout[2];
- pid_t child = fork_execv_on_steroids(flags, args, pipeout, (char**)unsetenv_vec,
/*dir:*/ NULL, uid);
-
- /* We use this function to run gdb and unstrip. Bugs in gdb or corrupted
- * coredumps were observed to cause gdb to enter infinite loop.
- * Therefore we have a (largish) timeout, after which we kill the child.
- */
- int t = time(NULL); /* int is enough, no need to use time_t */
- int endtime = t + timeout_sec;
-
- struct strbuf *buf_out = strbuf_new();
-
- while (1)
- {
- int timeout = endtime - t;
- if (timeout < 0)
- {
- kill(child, SIGKILL);
- strbuf_append_strf(buf_out, "\nTimeout exceeded: %u seconds, killing
%s\n", timeout_sec, args[0]);
- break;
- }
-
- /* We don't check poll result - checking read result is enough */
- struct pollfd pfd;
- pfd.fd = pipeout[0];
- pfd.events = POLLIN;
- poll(&pfd, 1, timeout * 1000);
-
- char buff[1024];
- int r = read(pipeout[0], buff, sizeof(buff) - 1);
- if (r <= 0)
- break;
- buff[r] = '\0';
- strbuf_append_str(buf_out, buff);
- t = time(NULL);
- }
- close(pipeout[0]);
-
- /* Prevent having zombie child process, and maybe collect status
- * (note that status == NULL is ok too) */
- waitpid(child, status, 0);
-
- return strbuf_free_nobuf(buf_out);
-}
-
static void gen_backtrace(const char *pDebugDumpDir, const char *pDebugInfoDirs, unsigned
timeout_sec)
{
update_client(_("Generating backtrace"));
@@ -178,56 +106,6 @@ static void gen_backtrace(const char *pD
waitpid(pid, NULL, 0);
}
-static void GetIndependentBuildIdPC(const char *unstrip_n_output,
- string& pIndependentBuildIdPC)
-{
- // lines look like this:
- // 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
- // 0x400000+0x209000 ab3c8286aac6c043fd1bb1cc2a0b88ec29517d3e@0x40024c /bin/sleep
/usr/lib/debug/bin/sleep.debug [exe]
- // 0x7fff313ff000+0x1000 389c7475e3d5401c55953a425a2042ef62c4c7df@0x7fff313ff2f8 . -
linux-vdso.so.1
- const char *line = unstrip_n_output;
- while (*line)
- {
- const char *eol = strchrnul(line, '\n');
- const char *plus = (char*)memchr(line, '+', eol - line);
- if (plus)
- {
- while (++plus < eol && *plus != '@')
- {
- if (!isspace(*plus))
- {
- pIndependentBuildIdPC += *plus;
- }
- }
- }
- if (*eol != '\n') break;
- line = eol + 1;
- }
-}
-
-static char* run_unstrip_n(const char *pDebugDumpDir, unsigned timeout_sec)
-{
- struct dump_dir *dd = dd_init();
- if (!dd_opendir(dd, pDebugDumpDir, DD_CLOSE_ON_OPEN_ERR))
- return NULL;
-
- char *uid = dd_load_text(dd, CD_UID);
- dd_close(dd);
-
- char* args[4];
- args[0] = (char*)"eu-unstrip";
- args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, pDebugDumpDir);
- args[2] = (char*)"-n";
- args[3] = NULL;
-
- char *out = exec_vp(args, xatoi_u(uid), /*redirect_stderr:*/ 0, timeout_sec, NULL);
- free(uid);
-
- free(args[1]);
-
- return out;
-}
-
/* Needs gdb feature from here:
https://bugzilla.redhat.com/show_bug.cgi?id=528668
* It is slated to be in F12/RHEL6.
*
@@ -397,59 +275,47 @@ static void trim_debuginfo_cache(unsigne
string CAnalyzerCCpp::GetLocalUUID(const char *pDebugDumpDir)
{
+ string ret;
+
struct dump_dir *dd = dd_init();
if (!dd_opendir(dd, pDebugDumpDir, DD_CLOSE_ON_OPEN_ERR))
- return string("");
-
- char *executable = dd_load_text(dd, FILENAME_EXECUTABLE);
- char *package = dd_load_text(dd, FILENAME_PACKAGE);
- dd_close(dd);
-
- string independentBuildIdPC;
- char *unstrip_n_output = run_unstrip_n(pDebugDumpDir, m_nGdbTimeoutSec);
- if (unstrip_n_output)
- GetIndependentBuildIdPC(unstrip_n_output, independentBuildIdPC);
- else
- VERB3 error_msg("run_unstrip_n() returns NULL, broken
coredump/eu-unstrip?");
-
- free(unstrip_n_output);
+ return ret; /* "" */
- /* package variable has "firefox-3.5.6-1.fc11[.1]" format */
- /* Remove distro suffix and maybe least significant version number */
- char *p = package;
- while (*p)
+ if (!dd_exist(dd, CD_UUID))
{
- if (*p == '.' && (p[1] < '0' || p[1] >
'9'))
+ dd_close(dd);
+
+ pid_t pid = fork();
+ if (pid < 0)
{
- /* We found "XXXX.nondigitXXXX", trim this part */
- *p = '\0';
- break;
+ perror_msg("fork");
+ return ret; /* "" */
}
- p++;
- }
- char *first_dot = strchr(package, '.');
- if (first_dot)
- {
- char *last_dot = strrchr(first_dot, '.');
- if (last_dot != first_dot)
+ if (pid == 0) /* child */
{
- /* There are more than one dot: "1.2.3"
- * Strip last part, we don't want to distinquish crashes
- * in packages which differ only by minor release number.
- */
- *last_dot = '\0';
- }
- }
+ char *argv[4]; /* abrt-action-analyze-c -d DIR <NULL> */
+ char **pp = argv;
+ *pp++ = (char*)"abrt-action-analyze-c";
+ *pp++ = (char*)"-d";
+ *pp++ = (char*)pDebugDumpDir;
+ *pp = NULL;
- char *hash_str = xasprintf("%s%s%s", package, executable,
independentBuildIdPC.c_str());
- free(package);
- free(executable);
+ execvp(argv[0], argv);
+ perror_msg_and_die("Can't execute '%s'", argv[0]);
+ }
+ /* parent */
+ waitpid(pid, NULL, 0);
- char hash_str2[SHA1_RESULT_LEN*2 + 1];
- create_hash(hash_str2, hash_str);
- free(hash_str);
+ dd = dd_init();
+ if (!dd_opendir(dd, pDebugDumpDir, DD_CLOSE_ON_OPEN_ERR))
+ return ret; /* "" */
+ }
- return hash_str2;
+ char *uuid = dd_load_text(dd, CD_UUID);
+ dd_close(dd);
+ ret = uuid;
+ free(uuid);
+ return ret;
}
string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
diff -x '*.po' -d -urpN abrt.6/src/daemon/abrt-action-analyze-c.c
abrt.7/src/daemon/abrt-action-analyze-c.c
--- abrt.6/src/daemon/abrt-action-analyze-c.c 1970-01-01 01:00:00.000000000 +0100
+++ abrt.7/src/daemon/abrt-action-analyze-c.c 2010-10-13 12:10:59.103186063 +0200
@@ -0,0 +1,262 @@
+/*
+ Copyright (C) 2009 Zdenek Prikryl (zprikryl(a)redhat.com)
+ 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 "abrtlib.h"
+#include "parse_options.h"
+
+#define PROGNAME "abrt-action-analyze-c"
+
+static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput)
+{
+ unsigned len;
+ unsigned char hash2[SHA1_RESULT_LEN];
+ sha1_ctx_t sha1ctx;
+
+ sha1_begin(&sha1ctx);
+ sha1_hash(pInput, strlen(pInput), &sha1ctx);
+ sha1_end(hash2, &sha1ctx);
+ len = SHA1_RESULT_LEN;
+
+ char *d = hash_str;
+ unsigned char *s = hash2;
+ while (len)
+ {
+ *d++ = "0123456789abcdef"[*s >> 4];
+ *d++ = "0123456789abcdef"[*s & 0xf];
+ s++;
+ len--;
+ }
+ *d = '\0';
+ //log("hash2:%s str:'%s'", hash_str, pInput);
+}
+
+/**
+ *
+ * @param[out] status See `man 2 wait` for status information.
+ * @return Malloc'ed string
+ */
+static char* exec_vp(char **args, uid_t uid, int redirect_stderr, unsigned timeout_sec,
int *status)
+{
+ /* Nuke everything which may make setlocale() switch to non-POSIX locale:
+ * we need to avoid having gdb output in some obscure language.
+ */
+ static const char *const unsetenv_vec[] = {
+ "LANG",
+ "LC_ALL",
+ "LC_COLLATE",
+ "LC_CTYPE",
+ "LC_MESSAGES",
+ "LC_MONETARY",
+ "LC_NUMERIC",
+ "LC_TIME",
+ NULL
+ };
+
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_SETGUID | EXECFLG_SETSID |
EXECFLG_QUIET;
+ if (redirect_stderr)
+ flags |= EXECFLG_ERR2OUT;
+ VERB1 flags &= ~EXECFLG_QUIET;
+
+ int pipeout[2];
+ pid_t child = fork_execv_on_steroids(flags, args, pipeout, (char**)unsetenv_vec,
/*dir:*/ NULL, uid);
+
+ /* We use this function to run gdb and unstrip. Bugs in gdb or corrupted
+ * coredumps were observed to cause gdb to enter infinite loop.
+ * Therefore we have a (largish) timeout, after which we kill the child.
+ */
+ int t = time(NULL); /* int is enough, no need to use time_t */
+ int endtime = t + timeout_sec;
+
+ struct strbuf *buf_out = strbuf_new();
+
+ while (1)
+ {
+ int timeout = endtime - t;
+ if (timeout < 0)
+ {
+ kill(child, SIGKILL);
+ strbuf_append_strf(buf_out, "\nTimeout exceeded: %u seconds, killing
%s\n", timeout_sec, args[0]);
+ break;
+ }
+
+ /* We don't check poll result - checking read result is enough */
+ struct pollfd pfd;
+ pfd.fd = pipeout[0];
+ pfd.events = POLLIN;
+ poll(&pfd, 1, timeout * 1000);
+
+ char buff[1024];
+ int r = read(pipeout[0], buff, sizeof(buff) - 1);
+ if (r <= 0)
+ break;
+ buff[r] = '\0';
+ strbuf_append_str(buf_out, buff);
+ t = time(NULL);
+ }
+ close(pipeout[0]);
+
+ /* Prevent having zombie child process, and maybe collect status
+ * (note that status == NULL is ok too) */
+ waitpid(child, status, 0);
+
+ return strbuf_free_nobuf(buf_out);
+}
+
+static char* run_unstrip_n(const char *dump_dir_name, unsigned timeout_sec)
+{
+ struct dump_dir *dd = dd_init();
+ if (!dd_opendir(dd, dump_dir_name, DD_CLOSE_ON_OPEN_ERR))
+ return NULL;
+ char *uid = dd_load_text(dd, CD_UID);
+ dd_close(dd);
+
+ char* args[4];
+ args[0] = (char*)"eu-unstrip";
+ args[1] = xasprintf("--core=%s/"FILENAME_COREDUMP, dump_dir_name);
+ args[2] = (char*)"-n";
+ args[3] = NULL;
+
+ char *out = exec_vp(args, xatoi_u(uid), /*redirect_stderr:*/ 0, timeout_sec, NULL);
+ free(uid);
+
+ free(args[1]);
+
+ return out;
+}
+
+static void trim_unstrip_output(char *result, const char *unstrip_n_output)
+{
+ // lines look like this:
+ // 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe]
+ // 0x400000+0x209000 ab3c8286aac6c043fd1bb1cc2a0b88ec29517d3e@0x40024c /bin/sleep
/usr/lib/debug/bin/sleep.debug [exe]
+ // 0x7fff313ff000+0x1000 389c7475e3d5401c55953a425a2042ef62c4c7df@0x7fff313ff2f8 . -
linux-vdso.so.1
+ // ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // we drop everything except the marked part ^
+
+ char *dst = result;
+ const char *line = unstrip_n_output;
+ while (*line)
+ {
+ const char *eol = strchrnul(line, '\n');
+ const char *plus = (char*)memchr(line, '+', eol - line);
+ if (plus)
+ {
+ while (++plus < eol && *plus != '@')
+ {
+ if (!isspace(*plus))
+ {
+ *dst++ = *plus;
+ }
+ }
+ }
+ if (*eol != '\n') break;
+ line = eol + 1;
+ }
+ *dst = '\0';
+}
+
+static const char program_usage_string[] = PROGNAME" [-v] -d DIR\n\n"
+ "Calculates and saves UUID";
+static const char *dump_dir_name = ".";
+enum {
+ OPT_v = 1 << 0,
+ OPT_d = 1 << 1,
+};
+/* Keep enum above and order of options below in sync! */
+static struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_STRING('d', NULL, &dump_dir_name, "DIR", "Crash dump
directory"),
+// OPT_BOOL( 's', NULL, NULL, "Log to syslog"
),
+ OPT_END()
+};
+
+int main(int argc, char **argv)
+{
+ char *env_verbose = getenv("ABRT_VERBOSE");
+ if (env_verbose)
+ g_verbose = atoi(env_verbose);
+
+ /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string);
+
+ putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose));
+
+//Maybe we will want this... later
+// msg_prefix = xasprintf(PROGNAME"[%u]", getpid());
+// if (opts & OPT_s)
+// {
+// openlog(msg_prefix, 0, LOG_DAEMON);
+// logmode = LOGMODE_SYSLOG;
+// }
+
+ /* Run unstrip -n and trim its output, leaving only sizes and build ids */
+
+ char *unstrip_n_output = run_unstrip_n(dump_dir_name, /*timeout_sec:*/ 30);
+ if (!unstrip_n_output)
+ return 1; /* bad dump_dir_name, can't run unstrip, etc... */
+ /* modifies unstrip_n_output in-place: */
+ trim_unstrip_output(unstrip_n_output, unstrip_n_output);
+
+ /* Hash package + executable + unstrip_n_output and save it as UUID */
+
+ struct dump_dir *dd = dd_init();
+ if (!dd_opendir(dd, dump_dir_name, DD_CLOSE_ON_OPEN_ERR))
+ return 1;
+
+ char *executable = dd_load_text(dd, FILENAME_EXECUTABLE);
+ char *package = dd_load_text(dd, FILENAME_PACKAGE);
+ /* Package variable has "firefox-3.5.6-1.fc11[.1]" format */
+ /* Remove distro suffix and maybe least significant version number */
+ char *p = package;
+ while (*p)
+ {
+ if (*p == '.' && (p[1] < '0' || p[1] >
'9'))
+ {
+ /* We found "XXXX.nondigitXXXX", trim this part */
+ *p = '\0';
+ break;
+ }
+ p++;
+ }
+ char *first_dot = strchr(package, '.');
+ if (first_dot)
+ {
+ char *last_dot = strrchr(first_dot, '.');
+ if (last_dot != first_dot)
+ {
+ /* There are more than one dot: "1.2.3"
+ * Strip last part, we don't want to distinquish crashes
+ * in packages which differ only by minor release number.
+ */
+ *last_dot = '\0';
+ }
+ }
+
+ char *string_to_hash = xasprintf("%s%s%s", package, executable,
unstrip_n_output);
+ /*free(package);*/
+ /*free(executable);*/
+ /*free(unstrip_n_output);*/
+
+ char hash_str[SHA1_RESULT_LEN*2 + 1];
+ create_hash(hash_str, string_to_hash);
+ /*free(hash_str);*/
+
+ dd_save_text(dd, CD_UUID, hash_str);
+ dd_close(dd);
+
+ return 0;
+}
diff -x '*.po' -d -urpN abrt.6/src/daemon/Makefile.am
abrt.7/src/daemon/Makefile.am
--- abrt.6/src/daemon/Makefile.am 2010-10-11 19:32:47.000000000 +0200
+++ abrt.7/src/daemon/Makefile.am 2010-10-13 11:40:05.616478724 +0200
@@ -4,6 +4,7 @@ bin_SCRIPTS = \
sbin_PROGRAMS = abrtd \
abrt-server \
+ abrt-action-analyze-c \
abrt-action-generate-backtrace \
abrt-action-save-package-data
@@ -58,6 +59,24 @@ abrt_server_CPPFLAGS = \
abrt_server_LDADD = \
../../lib/utils/libABRTUtils.la
+abrt_action_analyze_c_SOURCES = \
+ abrt-action-analyze-c.c
+abrt_action_analyze_c_CPPFLAGS = \
+ -I$(srcdir)/../../inc \
+ -I$(srcdir)/../../lib/utils \
+ -DBIN_DIR=\"$(bindir)\" \
+ -DVAR_RUN=\"$(VAR_RUN)\" \
+ -DCONF_DIR=\"$(CONF_DIR)\" \
+ -DLOCALSTATEDIR='"$(localstatedir)"' \
+ -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
+ -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
+ -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
+ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ -D_GNU_SOURCE \
+ -Wall -Werror
+abrt_action_analyze_c_LDADD = \
+ ../../lib/utils/libABRTUtils.la
+
abrt_action_generate_backtrace_SOURCES = \
abrt-action-generate-backtrace.c
abrt_action_generate_backtrace_CPPFLAGS = \
diff -x '*.po' -d -urpN abrt.6/src/gui/CCDump.py abrt.7/src/gui/CCDump.py
--- abrt.6/src/gui/CCDump.py 2010-10-11 19:21:31.000000000 +0200
+++ abrt.7/src/gui/CCDump.py 2010-10-13 13:09:26.305580137 +0200
@@ -36,7 +36,7 @@ FILENAME_HOSTNAME = "hostname"
FILENAME_REMOTE = "remote"
CD_UID = "uid"
-CD_UUID = "UUID"
+CD_UUID = "uuid"
CD_INFORMALL = "InformAll"
CD_DUMPDIR = "DumpDir"
CD_COUNT = "Count"
@@ -70,7 +70,7 @@ class Dump():
return "Dump instance"
def getUUID(self):
- return self.UUID
+ return self.uuid
def getUID(self):
return self.uid