diff options
-rw-r--r-- | inc/analyzer.h | 7 | ||||
-rw-r--r-- | inc/crash_types.h | 4 | ||||
-rw-r--r-- | lib/plugins/CCpp.cpp | 294 | ||||
-rw-r--r-- | lib/plugins/CCpp.h | 1 | ||||
-rw-r--r-- | lib/plugins/Kerneloops.h | 1 | ||||
-rw-r--r-- | lib/plugins/Python.h | 1 | ||||
-rw-r--r-- | src/daemon/MiddleWare.cpp | 139 | ||||
-rw-r--r-- | src/daemon/abrt_event.conf | 12 |
8 files changed, 18 insertions, 441 deletions
diff --git a/inc/analyzer.h b/inc/analyzer.h index 122b222e..3f2c6952 100644 --- a/inc/analyzer.h +++ b/inc/analyzer.h @@ -36,13 +36,6 @@ class CAnalyzer : public CPlugin * @return A global UUID. */ virtual std::string GetGlobalUUID(const char *pDebugDumpDir) = 0; - /** - * A method, which takes care of getting all additional data needed - * for computing UUIDs and creating a report. This report could be send - * somewhere afterwards. - * @param pDebugDumpPath A debugdump dir containing all necessary data. - */ - virtual void CreateReport(const char *pDebugDumpDir, int force) = 0; }; #endif /*ANALYZER_H_*/ diff --git a/inc/crash_types.h b/inc/crash_types.h index 6308db89..96d05d38 100644 --- a/inc/crash_types.h +++ b/inc/crash_types.h @@ -33,9 +33,7 @@ #define FILENAME_COREDUMP "coredump" #define FILENAME_BACKTRACE "backtrace" #define FILENAME_MEMORYMAP "memorymap" -// Used by CCpp analyzer to cache GetGlobalUUID() calls. -// FIXME! make ALL analyzers to save it as a file! -// Now, Python and kerneloops do not! +// Used to cache GetGlobalUUID() calls #define FILENAME_DUPHASH "global_uuid" /* name is compat, to be renamed to "duphash" */ // Name of the function where the application crashed. // Optional. diff --git a/lib/plugins/CCpp.cpp b/lib/plugins/CCpp.cpp index 7415891f..ddc17206 100644 --- a/lib/plugins/CCpp.cpp +++ b/lib/plugins/CCpp.cpp @@ -74,197 +74,6 @@ static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput //log("hash2:%s str:'%s'", hash_str, pInput); } -static void gen_backtrace(const char *pDebugDumpDir, const char *pDebugInfoDirs, unsigned timeout_sec) -{ - update_client(_("Generating backtrace")); - - pid_t pid = fork(); - if (pid < 0) - { - perror_msg("fork"); - return; - } - if (pid == 0) /* child */ - { - char *argv[8]; /* abrt-action-generate-backtrace [-s] -tSEC -d DIR -i DIR1:DIR2 NULL */ - char **pp = argv; - *pp++ = (char*)"abrt-action-generate-backtrace"; - if (logmode & LOGMODE_SYSLOG) - *pp++ = (char*)"-s"; - *pp++ = xasprintf("-t%u", timeout_sec); - *pp++ = (char*)"-d"; - *pp++ = (char*)pDebugDumpDir; - *pp++ = (char*)"-i"; - *pp++ = (char*)pDebugInfoDirs; - *pp = NULL; - - execvp(argv[0], argv); - perror_msg_and_die("Can't execute '%s'", argv[0]); - } - /* parent */ - waitpid(pid, NULL, 0); -} - -/* Needs gdb feature from here: https://bugzilla.redhat.com/show_bug.cgi?id=528668 - * It is slated to be in F12/RHEL6. - * - * returned value must be freed - */ -static char *install_debug_infos(const char *pDebugDumpDir, const char *debuginfo_dirs) -{ - update_client(_("Starting the debuginfo installation")); - - int pipeout[2]; //TODO: can we use ExecVP? - xpipe(pipeout); - - fflush(NULL); - pid_t child = fork(); - if (child < 0) - { - /*close(pipeout[0]); - why bother */ - /*close(pipeout[1]); */ - perror_msg_and_die("fork"); - } - if (child == 0) - { - close(pipeout[0]); - xmove_fd(pipeout[1], STDOUT_FILENO); - xmove_fd(xopen("/dev/null", O_RDONLY), STDIN_FILENO); - - char *coredump = xasprintf("%s/"FILENAME_COREDUMP, pDebugDumpDir); - /* SELinux guys are not happy with /tmp, using /var/run/abrt */ - char *tempdir = xasprintf(LOCALSTATEDIR"/run/abrt/tmp-%lu-%lu", (long)getpid(), (long)time(NULL)); - /* log() goes to stderr/syslog, it's ok to use it here */ - VERB1 log("Executing: %s %s %s %s", "abrt-action-install-debuginfo", coredump, tempdir, debuginfo_dirs); - /* We want parent to see errors in the same stream */ - xdup2(STDOUT_FILENO, STDERR_FILENO); - execlp("abrt-action-install-debuginfo", "abrt-action-install-debuginfo", coredump, tempdir, debuginfo_dirs, NULL); - perror_msg("Can't execute '%s'", "abrt-action-install-debuginfo"); - /* Serious error (1 means "some debuginfos not found") */ - exit(2); - } - - close(pipeout[1]); - - FILE *pipeout_fp = fdopen(pipeout[0], "r"); - if (pipeout_fp == NULL) /* never happens */ - { - close(pipeout[0]); - waitpid(child, NULL, 0); - return NULL; - } - - char *buff; - struct strbuf *buf_build_ids = strbuf_new(); - while ((buff = xmalloc_fgetline(pipeout_fp)) != NULL) - { - if (strncmp(buff, "MISSING:", 8) == 0) - { - strbuf_append_strf(buf_build_ids, "Debuginfo absent: %s\n", buff + 8); - free(buff); - continue; - } - - const char *p = buff; - while (*p == ' ' || *p == '\t') - { - p++; - } - - if (*p) - { - VERB1 log("%s", buff); - update_client("%s", buff); - } - free(buff); - } - fclose(pipeout_fp); - - int status = 0; - while (waitpid(child, &status, 0) < 0 && errno == EINTR) - continue; - if (WIFEXITED(status)) - { - if (WEXITSTATUS(status) > 1) - error_msg("%s exited with %u", "abrt-action-install-debuginfo", (int)WEXITSTATUS(status)); - } - else - { - error_msg("%s killed by signal %u", "abrt-action-install-debuginfo", (int)WTERMSIG(status)); - } - - return strbuf_free_nobuf(buf_build_ids); -} - -static double get_dir_size(const char *dirname, - string *worst_file, - double *maxsz) -{ - DIR *dp = opendir(dirname); - if (dp == NULL) - return 0; - - struct dirent *ep; - struct stat stats; - double size = 0; - while ((ep = readdir(dp)) != NULL) - { - if (dot_or_dotdot(ep->d_name)) - continue; - char *dname = concat_path_file(dirname, ep->d_name); - if (lstat(dname, &stats) != 0) - { - free(dname); - continue; - } - if (S_ISDIR(stats.st_mode)) - { - double sz = get_dir_size(dname, worst_file, maxsz); - size += sz; - } - else if (S_ISREG(stats.st_mode)) - { - double sz = stats.st_size; - size += sz; - - if (worst_file) - { - /* Calculate "weighted" size and age - * w = sz_kbytes * age_mins */ - sz /= 1024; - long age = (time(NULL) - stats.st_mtime) / 60; - if (age > 0) - sz *= age; - - if (sz > *maxsz) - { - *maxsz = sz; - *worst_file = dname; - } - } - } - free(dname); - } - closedir(dp); - return size; -} - -static void trim_debuginfo_cache(unsigned max_mb) -{ - while (1) - { - string worst_file; - double maxsz = 0; - double cache_sz = get_dir_size(DEBUGINFO_CACHE_DIR, &worst_file, &maxsz); - if (cache_sz / (1024 * 1024) < max_mb) - break; - VERB1 log("%s is %.0f bytes (over %u MB), deleting '%s'", - DEBUGINFO_CACHE_DIR, cache_sz, max_mb, worst_file.c_str()); - if (unlink(worst_file.c_str()) != 0) - perror_msg("Can't unlink '%s'", worst_file.c_str()); - } -} - string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) { struct dump_dir *dd = dd_opendir(pDebugDumpDir, /*flags:*/ 0); @@ -402,109 +211,6 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir) } } -static bool DebuginfoCheckPolkit(uid_t uid) -{ - fflush(NULL); - int child_pid = fork(); - if (child_pid < 0) - { - perror_msg_and_die("fork"); - } - - if (child_pid == 0) - { - //child - xsetreuid(uid, uid); - PolkitResult result = polkit_check_authorization(getpid(), - "org.fedoraproject.abrt.install-debuginfos"); - exit(result != PolkitYes); //exit 1 (failure) if not allowed - } - - //parent - int status; - if (waitpid(child_pid, &status, 0) > 0 - && WIFEXITED(status) - && WEXITSTATUS(status) == 0 - ) { - return true; //authorization OK - } - log("UID %d is not authorized to install debuginfos", uid); - return false; -} - -void CAnalyzerCCpp::CreateReport(const char *pDebugDumpDir, int force) -{ - if (!m_bBacktrace) - { - return; - } - - struct dump_dir *dd = dd_opendir(pDebugDumpDir, /*flags:*/ 0); - if (!dd) - return; - - if (!force) - { - int bt_exists = dd_exist(dd, FILENAME_BACKTRACE); - if (bt_exists) - { - dd_close(dd); - return; /* backtrace already exists */ - } - } - - /* Skip remote crashes. */ - if (dd_exist(dd, FILENAME_REMOTE)) - { - char *remote_str = dd_load_text(dd, FILENAME_REMOTE); - bool remote = (remote_str[0] != '1'); - free(remote_str); - if (remote && !m_bBacktraceRemotes) - { - dd_close(dd); - return; - } - } - - char *uid = dd_load_text(dd, CD_UID); - dd_close(dd); /* do not keep dir locked longer than needed */ - - char *build_ids = NULL; - if (m_bInstallDebugInfo && DebuginfoCheckPolkit(xatoi_u(uid))) - { - if (m_nDebugInfoCacheMB > 0) - trim_debuginfo_cache(m_nDebugInfoCacheMB); - build_ids = install_debug_infos(pDebugDumpDir, m_sDebugInfoDirs.c_str()); - } - else - VERB1 log(_("Skipping the debuginfo installation")); - free(uid); - - /* Create and store backtrace and its hash. */ - gen_backtrace(pDebugDumpDir, m_sDebugInfoDirs.c_str(), m_nGdbTimeoutSec); - - dd = dd_opendir(pDebugDumpDir, /*flags:*/ 0); - if (!dd) - { - free(build_ids); - return; - } - - /* Add build_ids to backtrace */ - char *backtrace_str = dd_load_text(dd, FILENAME_BACKTRACE); - char *bt_build_ids = xasprintf("%s%s", backtrace_str, (build_ids) ? build_ids : ""); - dd_save_text(dd, FILENAME_BACKTRACE, bt_build_ids); - free(build_ids); - free(bt_build_ids); - free(backtrace_str); - - /* TODO: remove, it's much easier to collect in the coredump helper */ - if (m_bMemoryMap) - dd_save_text(dd, FILENAME_MEMORYMAP, "memory map of the crashed C/C++ application, not implemented yet"); - - dd_close(dd); -} - /* this is just a workaround until kernel changes it's behavior when handling pipes in core_pattern diff --git a/lib/plugins/CCpp.h b/lib/plugins/CCpp.h index e8040449..dcd80982 100644 --- a/lib/plugins/CCpp.h +++ b/lib/plugins/CCpp.h @@ -42,7 +42,6 @@ class CAnalyzerCCpp : public CAnalyzer public: CAnalyzerCCpp(); virtual std::string GetGlobalUUID(const char *pDebugDumpDir); - virtual void CreateReport(const char *pDebugDumpDir, int force); virtual void Init(); virtual void DeInit(); virtual void SetSettings(const map_plugin_settings_t& pSettings); diff --git a/lib/plugins/Kerneloops.h b/lib/plugins/Kerneloops.h index 10253fe4..af6bef0e 100644 --- a/lib/plugins/Kerneloops.h +++ b/lib/plugins/Kerneloops.h @@ -35,7 +35,6 @@ class CAnalyzerKerneloops : public CAnalyzer { public: virtual std::string GetGlobalUUID(const char *pDebugDumpDir); - virtual void CreateReport(const char *pDebugDumpDir, int force) {} }; #endif diff --git a/lib/plugins/Python.h b/lib/plugins/Python.h index ebb1ec6f..c862ad45 100644 --- a/lib/plugins/Python.h +++ b/lib/plugins/Python.h @@ -27,7 +27,6 @@ class CAnalyzerPython : public CAnalyzer { public: virtual std::string GetGlobalUUID(const char *pDebugDumpDir); - virtual void CreateReport(const char *pDebugDumpDir, int force) {} virtual void Init(); virtual void DeInit(); }; diff --git a/src/daemon/MiddleWare.cpp b/src/daemon/MiddleWare.cpp index d51813b2..af12bd21 100644 --- a/src/daemon/MiddleWare.cpp +++ b/src/daemon/MiddleWare.cpp @@ -51,9 +51,6 @@ static map_analyzer_actions_and_reporters_t s_mapAnalyzerActionsAndReporters; static vector_pair_string_string_t s_vectorActionsAndReporters; -static void RunAnalyzerActions(const char *pAnalyzer, const char* pPackageName, const char *pDebugDumpDir, int force); - - /** * Transforms a debugdump directory to inner crash * report form. This form is used for later reporting. @@ -103,23 +100,11 @@ static std::string GetGlobalUUID(const char *pAnalyzer, throw CABRTException(EXCEP_PLUGIN, "Error running '%s'", pAnalyzer); } -/** - * Take care of getting all additional data needed - * for computing UUIDs and creating a report for particular analyzer - * plugin. This report could be send somewhere afterwards. - * @param pAnalyzer A name of an analyzer plugin. - * @param pDebugDumpPath A debugdump dir containing all necessary data. - */ -static void run_analyzer_CreateReport(const char *pAnalyzer, - const char *pDebugDumpDir, - int force) +static char *do_log_and_update_client(char *log_line, void *param) { - CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(pAnalyzer); - if (analyzer) - { - analyzer->CreateReport(pDebugDumpDir, force); - } - /* else: GetAnalyzer() already complained, no need to handle it here */ + VERB1 log("%s", log_line); + update_client("%s", log_line); + return log_line; } /* @@ -159,32 +144,16 @@ mw_result_t CreateCrashReport(const char *crash_id, try { - struct dump_dir *dd = dd_opendir(row->db_dump_dir, /*flags:*/ 0); - if (!dd) + struct run_event_state *run_state = new_run_event_state(); + run_state->logging_callback = do_log_and_update_client; + int res = run_event(run_state, row->db_dump_dir, "analyze"); + free_run_event_state(run_state); + if (res != 0) { - r = MW_ERROR; + r = MW_PLUGIN_ERROR; goto ret; } - load_crash_data_from_debug_dump(dd, pCrashData); - dd_close(dd); - - std::string analyzer = get_crash_data_item_content(pCrashData, FILENAME_ANALYZER); - const char* package = get_crash_data_item_content_or_NULL(pCrashData, FILENAME_PACKAGE); - char* package_name = get_package_name_from_NVR_or_NULL(package); - - /* Run analyzer's CreateReport() method */ - VERB3 log(" run_analyzer_CreateReport('%s')", analyzer.c_str()); - run_analyzer_CreateReport(analyzer.c_str(), row->db_dump_dir, force); - - /* Run actions (only actions, not reporters!) from - * "ANALYZER[:COMPONENT] = ACTION1, REPORTER1, REPORTER2, ACTION2..." line - * in abrt.conf - */ - VERB3 log(" RunAnalyzerActions('%s','%s','%s',force=%d)", analyzer.c_str(), package_name, row->db_dump_dir, force); - RunAnalyzerActions(analyzer.c_str(), package_name, row->db_dump_dir, force); - free(package_name); - /* Do a load_crash_data_from_debug_dump from (possibly updated) * crash dump dir */ @@ -469,41 +438,6 @@ static bool is_debug_dump_saved(const char *debug_dump_dir) return row != NULL; } -/** - * Get a package name from executable name and save - * package description to particular debugdump directory of a crash. - * @param pExecutable A name of crashed application. - * @param pDebugDumpDir A debugdump dir containing all necessary data. - * @return It return results of operation. See mw_result_t. - */ -static mw_result_t SavePackageDescriptionToDebugDump(const char *pDebugDumpDir) -{ - pid_t pid = fork(); - if (pid < 0) - { - perror_msg("fork"); - return MW_ERROR; - } - if (pid == 0) /* child */ - { - char *argv[5]; /* abrt-action-save-package-data [-s] -d DIR NULL */ - char **pp = argv; - *pp++ = (char*)"abrt-action-save-package-data"; - if (logmode & LOGMODE_SYSLOG) - *pp++ = (char*)"-s"; - *pp++ = (char*)"-d"; - *pp++ = (char*)pDebugDumpDir; - *pp = NULL; - - execvp(argv[0], argv); - perror_msg_and_die("Can't execute '%s'", argv[0]); - } - /* parent */ - int status; - waitpid(pid, &status, 0); - return (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? MW_OK : MW_ERROR; -} - bool analyzer_has_InformAllUsers(const char *analyzer_name) { CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name); @@ -519,59 +453,6 @@ bool analyzer_has_InformAllUsers(const char *analyzer_name) } /** - * Execute all action plugins, which are associated to - * particular analyzer plugin. - * @param pAnalyzer A name of an analyzer plugin. - * @param pDebugDumpPath A debugdump dir containing all necessary data. - */ -static void RunAnalyzerActions(const char *pAnalyzer, const char *pPackageName, const char *pDebugDumpDir, int force) -{ - map_analyzer_actions_and_reporters_t::iterator analyzer; - if (pPackageName != NULL) - { - /*try to find analyzer:component first*/ - char *analyzer_component = xasprintf("%s:%s", pAnalyzer, pPackageName); - analyzer = s_mapAnalyzerActionsAndReporters.find(analyzer_component); - /* if we didn't find an action for specific package, use the generic one */ - if (analyzer == s_mapAnalyzerActionsAndReporters.end()) - { - VERB2 log("didn't find action for %s, trying just %s", analyzer_component, pAnalyzer); - map_analyzer_actions_and_reporters_t::iterator analyzer = s_mapAnalyzerActionsAndReporters.find(pAnalyzer); - } - free(analyzer_component); - } - else - { - VERB2 log("no package name specified, trying to find action for: %s", pAnalyzer); - analyzer = s_mapAnalyzerActionsAndReporters.find(pAnalyzer); - } - if (analyzer != s_mapAnalyzerActionsAndReporters.end()) - { - vector_pair_string_string_t::iterator it_a = analyzer->second.begin(); - for (; it_a != analyzer->second.end(); it_a++) - { - const char *plugin_name = it_a->first.c_str(); - CAction* action = g_pPluginManager->GetAction(plugin_name, /*silent:*/ true); - if (!action) - { - /* GetAction() already complained if no such plugin. - * If plugin exists but isn't an Action, it's not an error. - */ - continue; - } - try - { - action->Run(pDebugDumpDir, it_a->second.c_str(), force); - } - catch (CABRTException& e) - { - update_client("Action performed by '%s' was not successful: %s", plugin_name, e.what()); - } - } - } -} - -/** * Save a debugdump into database. If saving is * successful, then crash info is filled. Otherwise the crash info is * not changed. diff --git a/src/daemon/abrt_event.conf b/src/daemon/abrt_event.conf index a8df2896..5459ddfa 100644 --- a/src/daemon/abrt_event.conf +++ b/src/daemon/abrt_event.conf @@ -36,11 +36,13 @@ EVENT=post-create analyzer=oops abrt-action-analyze-oops # user interaction, uncomment this line: #EVENT=post-create analyzer=oops abrt-action-kerneloops +#TODO: implement this (or add this functionality to abrt-action-install-debuginfo): +#EVENT=analyze analyzer=CCpp trim-debuginfo-cache /var/cache/abrt-di 4096m EVENT=analyze analyzer=CCpp abrt-action-install-debuginfo "$DUMP_DIR/coredump" "/var/run/abrt/$$-$RANDOM" /var/cache/abrt-di EVENT=analyze analyzer=CCpp abrt-action-generate-backtrace -EVENT=report analyzer=oops abrt-action-kerneloops -EVENT=report_Bugzilla analyzer=CCpp abrt-action-bugzilla -EVENT=report_Logger analyzer=CCpp abrt-action-print >/var/log/abrt.log -EVENT=report_Bugzilla analyzer=python abrt-action-bugzilla -EVENT=report_Logger analyzer=python abrt-action-print >/var/log/abrt.log +EVENT=report analyzer=oops abrt-action-kerneloops +EVENT=report_Bugzilla analyzer=CCpp abrt-action-bugzilla +EVENT=report_Logger analyzer=CCpp abrt-action-print >/var/log/abrt.log +EVENT=report_Bugzilla analyzer=python abrt-action-bugzilla +EVENT=report_Logger analyzer=python abrt-action-print >/var/log/abrt.log |