diff options
author | Karel Klic <kklic@redhat.com> | 2009-11-12 16:58:07 +0100 |
---|---|---|
committer | Karel Klic <kklic@redhat.com> | 2009-11-12 16:58:07 +0100 |
commit | 32cee84a34c005fe0d2863f439007ec633687fa8 (patch) | |
tree | 149ca7014e4295de3788f28ae88e9d9d7003da46 /src | |
parent | 5a8a8a6c99c9067e0dfcce839c32826a2badff0b (diff) | |
parent | 3938e6e075867ae3a349ba307ee672aa458d2662 (diff) | |
download | abrt-32cee84a34c005fe0d2863f439007ec633687fa8.tar.gz abrt-32cee84a34c005fe0d2863f439007ec633687fa8.tar.xz abrt-32cee84a34c005fe0d2863f439007ec633687fa8.zip |
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
Diffstat (limited to 'src')
-rw-r--r-- | src/Daemon/Daemon.cpp | 60 | ||||
-rw-r--r-- | src/Daemon/MiddleWare.cpp | 51 | ||||
-rw-r--r-- | src/Daemon/MiddleWare.h | 7 | ||||
-rw-r--r-- | src/Daemon/Settings.cpp | 2 | ||||
-rwxr-xr-x | src/Daemon/abrt-debuginfo-install | 249 | ||||
-rw-r--r-- | src/Gui/CCMainWindow.py | 2 | ||||
-rw-r--r-- | src/Gui/CCReporterDialog.py | 29 | ||||
-rw-r--r-- | src/Gui/report.glade | 45 | ||||
-rw-r--r-- | src/Hooks/CCpp.cpp | 10 | ||||
-rw-r--r-- | src/Hooks/Makefile.am | 4 | ||||
-rw-r--r-- | src/Hooks/abrt-pyhook-helper.cpp | 14 | ||||
-rw-r--r-- | src/Hooks/abrt_exception_handler.py.in | 1 |
12 files changed, 279 insertions, 195 deletions
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 67e72cca..53c44d3f 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -165,18 +165,6 @@ static double GetDirSize(const std::string &pPath, std::string *worst_dir = NULL return size; } -static bool analyzer_has_InformAllUsers(const char *analyzer_name) -{ - CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name); - if (!analyzer) - return false; - map_plugin_settings_t settings = analyzer->GetSettings(); - map_plugin_settings_t::const_iterator it = settings.find("InformAllUsers"); - if (it == settings.end()) - return false; - return string_to_bool(it->second.c_str()); -} - static void cron_delete_callback_data_cb(gpointer data) { cron_callback_data_t* cronDeleteCallbackData = static_cast<cron_callback_data_t*>(data); @@ -388,23 +376,24 @@ static void FindNewDumps(const char* pPath) switch (res) { case MW_OK: - VERB1 log("Saving into database (%s)", itt->c_str()); + VERB1 log("Saving %s into database", itt->c_str()); RunActionsAndReporters(crashinfo[CD_MWDDD][CD_CONTENT].c_str()); break; case MW_IN_DB: - VERB1 log("Already saved in database (%s)", itt->c_str()); + VERB1 log("%s is already saved in database", itt->c_str()); break; case MW_REPORTED: case MW_OCCURED: + VERB1 log("Already saved crash %s, deleting", itt->c_str()); + DeleteDebugDumpDir(itt->c_str()); + break; case MW_BLACKLISTED: case MW_CORRUPTED: case MW_PACKAGE_ERROR: case MW_GPG_ERROR: case MW_FILE_ERROR: default: -//Perhaps corrupted & bad needs to be logged unconditionally, -//already saved one - only on VERB1 - VERB1 log("Corrupted, bad or already saved crash, deleting"); + log("Corrupted or bad crash %s (res:%d), deleting", itt->c_str(), (int)res); DeleteDebugDumpDir(itt->c_str()); break; } @@ -556,7 +545,6 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin : crashinfo[CD_UID][CD_CONTENT].c_str(); g_pCommLayer->Crash(crashinfo[CD_PACKAGE][CD_CONTENT].c_str(), uid_str); } - //DeleteDebugDumpDir(fullname.c_str()); break; case MW_BLACKLISTED: case MW_CORRUPTED: @@ -670,29 +658,36 @@ static void start_syslog_logging() logmode = LOGMODE_SYSLOG; } -static void ensure_root_writable_dir(const char *dir) +static void ensure_writable_dir(const char *dir, mode_t mode, const char *group) { struct stat sb; - if (mkdir(dir, 0755) != 0 && errno != EEXIST) + if (mkdir(dir, mode) != 0 && errno != EEXIST) perror_msg_and_die("Can't create '%s'", dir); if (stat(dir, &sb) != 0 || !S_ISDIR(sb.st_mode)) error_msg_and_die("'%s' is not a directory", dir); - if ((sb.st_uid != 0 || sb.st_gid != 0) && chown(dir, 0, 0) != 0) + + struct group *gr = getgrnam(group); + if (!gr) + perror_msg_and_die("Can't find group '%s'", group); + + if ((sb.st_uid != 0 || sb.st_gid != gr->gr_gid) && chown(dir, 0, gr->gr_gid) != 0) perror_msg_and_die("Can't set owner 0:0 on '%s'", dir); - /* We can't allow anyone to create dumps: otherwise users can flood - * us with thousands of bogus or malicious dumps */ - /* 07000 bits are setuid, setgit, and sticky, and they must be unset */ - /* 00777 bits are usual "rwxrwxrwx" access rights */ - if ((sb.st_mode & 07777) != 0755 && chmod(dir, 0755) != 0) - perror_msg_and_die("Can't set mode rwxr-xr-x on '%s'", dir); + if ((sb.st_mode & 07777) != mode && chmod(dir, mode) != 0) + perror_msg_and_die("Can't set mode %o on '%s'", mode, dir); } static void sanitize_dump_dir_rights() { - ensure_root_writable_dir(DEBUG_DUMPS_DIR); - ensure_root_writable_dir(DEBUG_DUMPS_DIR"-di"); /* debuginfo cache */ - ensure_root_writable_dir(VAR_RUN"/abrt"); /* temp dir */ + /* We can't allow anyone to create dumps: otherwise users can flood + * us with thousands of bogus or malicious dumps */ + /* 07000 bits are setuid, setgit, and sticky, and they must be unset */ + /* 00777 bits are usual "rwxrwxrwx" access rights */ + ensure_writable_dir(DEBUG_DUMPS_DIR, 0775, "abrt"); + /* debuginfo cache */ + ensure_writable_dir(DEBUG_DUMPS_DIR"-di", 0755, "root"); + /* temp dir */ + ensure_writable_dir(VAR_RUN"/abrt", 0755, "root"); } int main(int argc, char** argv) @@ -806,11 +801,6 @@ int main(int argc, char** argv) pMainloop = g_main_loop_new(NULL, FALSE); /* Watching DEBUG_DUMPS_DIR for new files... */ VERB1 log("Initializing inotify"); -// Enabled again since we have new abrt-pyhook-helper, remove comment when verified to work - /* FIXME: python hook runs with ordinary user privileges, - * so it fails if everyone doesn't have write acces - * to DEBUG_DUMPS_DIR - */ sanitize_dump_dir_rights(); errno = 0; int inotify_fd = inotify_init(); diff --git a/src/Daemon/MiddleWare.cpp b/src/Daemon/MiddleWare.cpp index 6a635642..0bc358e1 100644 --- a/src/Daemon/MiddleWare.cpp +++ b/src/Daemon/MiddleWare.cpp @@ -456,10 +456,9 @@ void DeleteDebugDumpDir(const char *pDebugDumpDir) std::string DeleteCrashInfo(const char *pUUID, const char *pUID) { - database_row_t row; CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); database->Connect(); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->Delete(pUUID, pUID); database->DisConnect(); @@ -573,6 +572,21 @@ static mw_result_t SavePackageDescriptionToDebugDump(const char *pExecutable, return MW_OK; } +bool analyzer_has_InformAllUsers(const char *analyzer_name) +{ + CAnalyzer* analyzer = g_pPluginManager->GetAnalyzer(analyzer_name); + if (!analyzer) + { + VERB1 log("Strange, asked for analyzer %s but it doesn't exist?", analyzer_name); + return false; + } + map_plugin_settings_t settings = analyzer->GetSettings(); + map_plugin_settings_t::const_iterator it = settings.find("InformAllUsers"); + if (it == settings.end()) + return false; + return string_to_bool(it->second.c_str()); +} + /** * Execute all action plugins, which are associated to * particular analyzer plugin. @@ -621,14 +635,12 @@ static mw_result_t SaveDebugDumpToDatabase(const char *pUUID, const char *pDebugDumpDir, map_crash_info_t& pCrashInfo) { - mw_result_t res; CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); - database_row_t row; database->Connect(); database->Insert(pUUID, pUID, pDebugDumpDir, pTime); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); - res = GetCrashInfo(pUUID, pUID, pCrashInfo); + mw_result_t res = GetCrashInfo(pUUID, pUID, pCrashInfo); if (row.m_sReported == "1") { log("Crash is already reported"); @@ -646,29 +658,19 @@ std::string getDebugDumpDir(const char *pUUID, const char *pUID) { CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); - database_row_t row; database->Connect(); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); return row.m_sDebugDumpDir; } -mw_result_t SaveDebugDump(const char *pDebugDumpDir) -{ - map_crash_info_t info; - return SaveDebugDump(pDebugDumpDir, info); -} - mw_result_t SaveDebugDump(const char *pDebugDumpDir, map_crash_info_t& pCrashInfo) { - std::string lUUID; std::string UID; std::string time; std::string analyzer; std::string executable; - mw_result_t res; - try { CDebugDump dd; @@ -692,15 +694,17 @@ mw_result_t SaveDebugDump(const char *pDebugDumpDir, { return MW_IN_DB; } - res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir); + mw_result_t res = SavePackageDescriptionToDebugDump(executable.c_str(), pDebugDumpDir); if (res != MW_OK) { return res; } - lUUID = GetLocalUUID(analyzer.c_str(), pDebugDumpDir); - - return SaveDebugDumpToDatabase(lUUID.c_str(), UID.c_str(), time.c_str(), pDebugDumpDir, pCrashInfo); + std::string lUUID = GetLocalUUID(analyzer.c_str(), pDebugDumpDir); + const char *uid_str = analyzer_has_InformAllUsers(analyzer.c_str()) + ? "-1" + : UID.c_str(); + return SaveDebugDumpToDatabase(lUUID.c_str(), uid_str, time.c_str(), pDebugDumpDir, pCrashInfo); } mw_result_t GetCrashInfo(const char *pUUID, @@ -709,16 +713,14 @@ mw_result_t GetCrashInfo(const char *pUUID, { pCrashInfo.clear(); CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase); - database_row_t row; database->Connect(); - row = database->GetUUIDData(pUUID, pUID); + database_row_t row = database->GetUUIDData(pUUID, pUID); database->DisConnect(); std::string package; std::string executable; std::string description; std::string analyzer; - try { CDebugDump dd; @@ -737,6 +739,7 @@ mw_result_t GetCrashInfo(const char *pUUID, } return MW_ERROR; } + add_crash_data_to_crash_info(pCrashInfo, CD_EXECUTABLE, executable); add_crash_data_to_crash_info(pCrashInfo, CD_PACKAGE, package); add_crash_data_to_crash_info(pCrashInfo, CD_DESCRIPTION, description); diff --git a/src/Daemon/MiddleWare.h b/src/Daemon/MiddleWare.h index 0671dd02..ac042def 100644 --- a/src/Daemon/MiddleWare.h +++ b/src/Daemon/MiddleWare.h @@ -120,12 +120,6 @@ void DeleteDebugDumpDir(const char *pDebugDumpDir); std::string DeleteCrashInfo(const char *pUUID, const char *pUID); /** - * Saves debugdump into database. - * @param pDebugDumpDir A debugdump directory. - * @return It return results of operation. See mw_result_t. - */ -mw_result_t SaveDebugDump(const char *pDebugDumpDir); -/** * Saves debugdump into database. If saving is successful, * it fills crash info. * @param pDebugDumpDir A debugdump directory. @@ -171,5 +165,6 @@ void AddAnalyzerActionOrReporter(const char *pAnalyzer, void AddActionOrReporter(const char *pActionOrReporter, const char *pArgs); +bool analyzer_has_InformAllUsers(const char *analyzer_name); #endif /*MIDDLEWARE_H_*/ diff --git a/src/Daemon/Settings.cpp b/src/Daemon/Settings.cpp index d9c9a98b..cefd35a4 100644 --- a/src/Daemon/Settings.cpp +++ b/src/Daemon/Settings.cpp @@ -132,7 +132,7 @@ static void ParseCommon() map_string_t::const_iterator end = s_mapSectionCommon.end(); if (it != end) { - g_settings_bOpenGPGCheck = it->second == "yes"; + g_settings_bOpenGPGCheck = string_to_bool(it->second.c_str()); } it = s_mapSectionCommon.find("OpenGPGPublicKeys"); if (it != end) diff --git a/src/Daemon/abrt-debuginfo-install b/src/Daemon/abrt-debuginfo-install index 6070b74d..b3d72922 100755 --- a/src/Daemon/abrt-debuginfo-install +++ b/src/Daemon/abrt-debuginfo-install @@ -80,22 +80,39 @@ count_words() { echo $# } -cleanup_and_report_missing() { -# Which debuginfo files are still missing, including those we just unpacked? - missing_build_ids=`for build_id in $build_ids; do +print_missing_build_ids() { + for build_id in $build_ids; do build_id1=${build_id:0:2} build_id2=${build_id:2} file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" test -f "/$file" && continue test -f "$cachedir/$file" && continue echo -n "$build_id " - done` + done +} + +print_missing_debuginfos() { + for build_id in $build_ids; do + build_id1=${build_id:0:2} + build_id2=${build_id:2} + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then + test -f "$cachedir/$file" && continue + fi + test -f "/$file" && continue + echo -n "/$file " + done +} + +cleanup_and_report_missing() { +# Which debuginfo files are still missing, including those we just unpacked? + missing_build_ids=`print_missing_build_ids` $debug && echo "missing_build_ids:$missing_build_ids" # If cachedir is specified, tempdir is just a staging area. Delete it if test x"$cachedir" != x""; then $debug && echo "Removing $tempdir" - rm -rf "$tempdir" + $debug || rm -rf "$tempdir" fi for missing in $missing_build_ids; do @@ -105,6 +122,98 @@ cleanup_and_report_missing() { test x"$missing_build_ids" != x"" && echo "`count_words $missing_build_ids` debuginfos can't be found" } +# $1: iteration (1,2...) +print_package_names() { + # We'll run something like: + # yum --enablerepo='*debuginfo*' --quiet provides \ + # /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \ + # /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ... + local yumopts="" + if test x"$1" = x"1"; then + yumopts="-C" + echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list from cache" >&2 + else + echo "`count_words $missing_debuginfo_files` missing debuginfos, getting package list" >&2 + fi + local cmd="yum $yumopts --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files" + echo "$cmd" >"yum_provides.$1.OUT" + local yum_provides_OUT=`$cmd 2>&1` + local err=$? + printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >>"yum_provides.$1.OUT" + test $err = 0 || exit 2 + + # The output is pretty machine-unfriendly: + # glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc + # Repo : rawhide-debuginfo + # Matched from: + # Filename : /usr/lib/debug/.build-id/5b/c784c8d63f87dbdeb747a773940956a18ecd2f.debug + # + # 1:dbus-debuginfo-1.2.12-2.fc11.x86_64 : Debug information for package dbus + # Repo : updates-debuginfo + # Matched from: + # Filename : /usr/lib/debug/.build-id/bc/da7d09eb6c9ee380dae0ed3d591d4311decc31.debug + # Need to massage it a lot. + # There can be duplicates (one package may provide many debuginfos). + printf "%s\n" "$yum_provides_OUT" \ + | grep -- -debuginfo- \ + | sed 's/^[0-9]*://' \ + | sed -e 's/ .*//' -e 's/:.*//' \ + | sort | uniq | xargs +} + +download_packages() { + ## Download with one command (too silent): + ## Redirecting, since progress bar stuff only messes up our output + ##yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 + ##err=$? + ##echo "exitcode:$err" >>yumdownloader.OUT + ##test $err = 0 || exit 2 + >yumdownloader.OUT + i=1 + for pkg in $packages; do + echo "Download $i/$num_packages: $pkg" + echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT + yumdownloader --enablerepo='*debuginfo*' --quiet $pkg >>yumdownloader.OUT 2>&1 + err=$? + echo "exitcode:$err" >>yumdownloader.OUT + echo >>yumdownloader.OUT + test $err = 0 || { echo "Download of $pkg failed!"; sleep 1; } + : $((i++)) + done + + for f in *.rpm; do + # Happens if no .rpm's were downloaded (yumdownloader problem) + # In this case, $f is the literal "*.rpm" string + test -f "$f" || exit 2 + echo "Unpacking: $f" + echo "Processing: $f" >>unpack.OUT + rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 + done + + # Copy debuginfo files to cachedir + if test x"$cachedir" != x"" && test -d "$cachedir"; then + for build_id in $build_ids; do + build_id1=${build_id:0:2} + build_id2=${build_id:2} + + file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + + test -f "/$file" && continue + test x"$cachedir" != x"/" && test -f "$cachedir/$file" && continue + + if test -f "$file"; then + # file is one of those we just installed. + # Cache it if cachedir is specified. + mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" + # Note: this does not preserve symlinks. This is intentional + $debug && echo Copying2 "$file" to "$cachedir/$file" >&2 + cp --remove-destination "$file" "$cachedir/$file" + continue + fi + done + fi +} + # eu-unstrip output example: # 0x400000+0x209000 23c77451cf6adff77fc1f5ee2a01d75de6511dda@0x40024c - - [exe] @@ -138,113 +247,39 @@ build_ids=`printf "%s\n" "$eu_unstrip_OUT" \ done | sort | uniq | xargs` $debug && echo "build_ids:$build_ids" -# Which debuginfo files are missing? -missing_debuginfo_files=`for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" - if test x"$cachedir" != x"" && test x"$cachedir" != x"/" ; then - test -f "$cachedir/$file" && continue - fi - test -f "/$file" && continue - echo -n "/$file " -done` -$debug && echo "missing_debuginfo_files:$missing_debuginfo_files" - -if test x"$missing_debuginfo_files" = x""; then - cleanup_and_report_missing - exit 0 -fi - -# We'll run something like: -# yum --enablerepo='*debuginfo*' --quiet provides \ -# /usr/lib/debug/.build-id/bb/11528d59940983f495e9cb099cafb0cb206051.debug \ -# /usr/lib/debug/.build-id/c5/b84c0ad3676509dc30bfa7d42191574dac5b06.debug ... -echo "Determining list of packages for `count_words $missing_debuginfo_files` missing debuginfos" -yum_provides_OUT=`yum --enablerepo='*debuginfo*' --quiet provides $missing_debuginfo_files 2>&1` -err=$? -printf "%s\nexitcode:%s\n" "$yum_provides_OUT" $err >yum_provides.OUT -test $err = 0 || exit 2 +# We try to not run yum without -C unless absolutely necessary. +# Therefore we loop. yum is run by print_package_names function, +# on first iteration it is run with -C, on second - without, +# which usually causes yum to download updated filelists, +# which in turn takes several minutes and annoys users. +iter=0 +while true; do + : $((iter++)) + test $iter -gt 2 && break -# The output is pretty machine-unfriendly: -# glibc-debuginfo-2.10.90-24.x86_64 : Debug information for package glibc -# Repo : rawhide-debuginfo -# Matched from: -# Filename : /usr/lib/debug/.build-id/5b/c784c8d63f87dbdeb747a773940956a18ecd2f.debug -# -# 1:dbus-debuginfo-1.2.12-2.fc11.x86_64 : Debug information for package dbus -# Repo : updates-debuginfo -# Matched from: -# Filename : /usr/lib/debug/.build-id/bc/da7d09eb6c9ee380dae0ed3d591d4311decc31.debug -# Need to massage it a lot. -# There can be duplicates (one package may provide many debuginfos). -packages=`printf "%s\n" "$yum_provides_OUT" \ -| grep -- -debuginfo- \ -| sed 's/^[0-9]*://' \ -| sed -e 's/ .*//' -e 's/:.*//' \ -| sort | uniq | xargs` -$debug && echo "packages:$packages" - -# yum may return "" here if it found no packages (say, if coredump is from a new, -# unreleased package fresh from koji). -if test x"$packages" = x""; then - cleanup_and_report_missing - exit 1 -fi - -num_packages=`count_words $packages` -echo "Downloading $num_packages packages" -## Download with one command (too silent): -## Redirecting, since progress bar stuff only messes up our output -##yumdownloader --enablerepo='*debuginfo*' --quiet $packages >yumdownloader.OUT 2>&1 -##err=$? -##echo "exitcode:$err" >>yumdownloader.OUT -##test $err = 0 || exit 2 ->yumdownloader.OUT -i=1 -for pkg in $packages; do - echo "Download $i/$num_packages: $pkg" - echo "Download $i/$num_packages: $pkg" >>yumdownloader.OUT - yumdownloader --enablerepo='*debuginfo*' --quiet $pkg >>yumdownloader.OUT 2>&1 - err=$? - echo "exitcode:$err" >>yumdownloader.OUT - echo >>yumdownloader.OUT - test $err = 0 || { echo "Download of $pkg failed!"; sleep 1; } - : $((i++)) -done + # Analyze $build_ids and check which debuginfos are present + missing_debuginfo_files=`print_missing_debuginfos` + $debug && echo "missing_debuginfo_files:$missing_debuginfo_files" -for f in *.rpm; do - # Happens if no .rpm's were downloaded (yumdownloader problem) - # In this case, $f is the literal "*.rpm" string - test -f "$f" || exit 2 - echo "Unpacking: $f" - echo "Processing: $f" >>unpack.OUT - rpm2cpio <"$f" 2>>unpack.OUT | cpio -id >>unpack.OUT 2>&1 -done + if test x"$missing_debuginfo_files" = x""; then + break + fi -# Copy debuginfo files to cachedir -if test x"$cachedir" != x"" && test -d "$cachedir"; then - for build_id in $build_ids; do - build_id1=${build_id:0:2} - build_id2=${build_id:2} + # Map $missing_debuginfo_files to package names. + # yum is run here. + packages=`print_package_names $iter` + $debug && echo "packages ($iter):$packages" - file="usr/lib/debug/.build-id/$build_id1/$build_id2.debug" + # yum may return "" here if it found no packages (say, if coredump + # is from a new, unreleased package fresh from koji). + if test x"$packages" = x""; then + continue + fi - test -f "/$file" && continue - test x"$cachedir" != x"/" && test -f "$cachedir/$file" && continue - - if test -f "$file"; then - # file is one of those we just installed. - # Cache it if cachedir is specified. - mkdir -p "$cachedir/usr/lib/debug/.build-id/$build_id1" - # Note: this does not preserve symlinks. This is intentional - $debug && echo Copying2 "$file" to "$cachedir/$file" >&2 - cp --remove-destination "$file" "$cachedir/$file" - continue - fi - done -fi -$debug && echo "missing_build_ids:$missing_build_ids" + num_packages=`count_words $packages` + echo "Downloading $num_packages packages" + download_packages +done cleanup_and_report_missing diff --git a/src/Gui/CCMainWindow.py b/src/Gui/CCMainWindow.py index d3a3abd0..31ebb410 100644 --- a/src/Gui/CCMainWindow.py +++ b/src/Gui/CCMainWindow.py @@ -88,7 +88,7 @@ class MainWindow(): columns[0] = gtk.TreeViewColumn(_("Package")) columns[1] = gtk.TreeViewColumn(_("Application")) columns[2] = gtk.TreeViewColumn(_("Date")) - columns[3] = gtk.TreeViewColumn(_("Crash Rate")) + columns[3] = gtk.TreeViewColumn(_("Crash count")) if os.getuid() == 0: column = gtk.TreeViewColumn(_("User")) columns.append(column) diff --git a/src/Gui/CCReporterDialog.py b/src/Gui/CCReporterDialog.py index e1d1c1bb..61e65526 100644 --- a/src/Gui/CCReporterDialog.py +++ b/src/Gui/CCReporterDialog.py @@ -43,6 +43,10 @@ class ReporterDialog(): self.tvComment = self.wTree.get_widget("tvComment") self.tvComment.connect("focus-in-event", self.on_comment_focus_cb) self.comment_changed = False + + # "how to reproduce" textview + self.tevHowToReproduce = self.wTree.get_widget("tevHowToReproduce") + self.how_to_changed = False self.tvReport = self.wTree.get_widget("tvReport") @@ -76,7 +80,7 @@ class ReporterDialog(): # connect the signals self.tvReport.connect_after("size-allocate", self.on_window_resize) self.wTree.get_widget("bSend").connect("clicked", self.on_send_clicked) - # start whit the warning hidden, so it's not visible when there is no rating + # start with the warning hidden, so it's not visible when there is no rating self.wTree.get_widget("ebErrors").hide() self.hydrate() @@ -182,6 +186,20 @@ class ReporterDialog(): self.tvComment.set_buffer(buff) continue + if item == "How to reproduce": + buff = gtk.TextBuffer() + how_to_reproduce = _("") + try: + if self.report[item][CONTENT]: + how_to_reproduce = self.report[item][CONTENT] + self.how_to_changed = True + except Exception, e: + pass + + buff.set_text(how_to_reproduce) + + self.tevHowToReproduce.set_buffer(buff) + continue # if an backtrace has rating use it if item == "rating": try: @@ -198,7 +216,7 @@ class ReporterDialog(): ebErrors.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("red")) if package: lErrors.set_markup( - "<span color=\"white\">%s</span>" % _("Reporting disabled because the backtrace is unusable!\nPlease try to install debuginfo manually using command:<span color=\"blue\"> debuginfo-install %s </span>\nthen use Refresh button to regenerate the backtrace." % package[0:package.rfind('-',0,package.rfind('-'))])) + "<span color=\"white\">%s</span>" % _("Reporting disabled because the backtrace is unusable.\nPlease try to install debuginfo manually using command:<span color=\"blue\"> debuginfo-install %s </span>\nthen use Refresh button to regenerate the backtrace." % package[0:package.rfind('-',0,package.rfind('-'))])) else: lErrors.set_markup("<span color=\"white\">%s</span>" % _("The bactrace is unusable, you can't report this!")) bSend.set_sensitive(False) @@ -232,11 +250,18 @@ class ReporterDialog(): self.report[rowe["item"]][CONTENT] = rowe["content"] else: del self.report[rowe["item"]] + # handle comment if self.comment_changed: buff = self.tvComment.get_buffer() self.report["Comment"] = ['t', 'y', buff.get_text(buff.get_start_iter(),buff.get_end_iter())] else: del self.report["Comment"] + # handle how to reproduce + if self.how_to_changed: + buff = self.tevHowToReproduce.get_buffer() + self.report["How to reproduce"] = ['t', 'y', buff.get_text(buff.get_start_iter(),buff.get_end_iter())] + else: + del self.report["How to reproduce"] def on_send_clicked(self, button): #def on_apply_clicked(self, button, treeview): diff --git a/src/Gui/report.glade b/src/Gui/report.glade index 2ccf1690..ce21acb1 100644 --- a/src/Gui/report.glade +++ b/src/Gui/report.glade @@ -69,7 +69,50 @@ </packing> </child> <child> - <placeholder/> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <widget class="GtkEventBox" id="eventbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="lHowToReproduce"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">2</property> + <property name="label" translatable="yes">How to reproduce (in a few simple steps)</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">never</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <widget class="GtkTextView" id="tevHowToReproduce"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="wrap_mode">word</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> </child> <child> <widget class="GtkVBox" id="vbox1"> diff --git a/src/Hooks/CCpp.cpp b/src/Hooks/CCpp.cpp index 0f95d05b..3ab8f406 100644 --- a/src/Hooks/CCpp.cpp +++ b/src/Hooks/CCpp.cpp @@ -205,19 +205,19 @@ int main(int argc, char** argv) dd.Close(); perror_msg_and_die("can't open '%s'", path); } - if (copyfd_eof(STDIN_FILENO, fd) < 0) + off_t size = copyfd_eof(STDIN_FILENO, fd); + if (size < 0 || close(fd) != 0) { - /* close(fd); - why bother? */ + unlink(path); dd.Delete(); dd.Close(); /* copyfd_eof logs the error including errno string, * but it does not log file name */ error_msg_and_die("error saving coredump to %s", path); } - /* close(fd); - why bother? */ - /* free(executable); */ + /* free(executable); - why bother? */ /* free(cmdline); */ - log("saved core dump of pid %u to %s", (int)pid, path); + log("saved core dump of pid %u to %s (%llu bytes)", (int)pid, path, (long long)size); } catch (CABRTException& e) { diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am index 4eb25e2d..e581c25b 100644 --- a/src/Hooks/Makefile.am +++ b/src/Hooks/Makefile.am @@ -57,7 +57,3 @@ 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 index 8a5a1914..08ccc125 100644 --- a/src/Hooks/abrt-pyhook-helper.cpp +++ b/src/Hooks/abrt-pyhook-helper.cpp @@ -20,6 +20,7 @@ */ #include <getopt.h> +#include <unistd.h> /* We can easily get rid of abrtlib (libABRTUtils.so) usage in this file, * but DebugDump will pull it in anyway */ #include "abrtlib.h" @@ -34,7 +35,6 @@ static char *pid; static char *executable; static char *uuid; static char *cmdline; -static char *loginuid; int main(int argc, char** argv) { @@ -45,7 +45,6 @@ int main(int argc, char** argv) { "executable", required_argument, NULL, 'e' }, { "uuid" , required_argument, NULL, 'u' }, { "cmdline" , required_argument, NULL, 'c' }, - { "loginuid" , required_argument, NULL, 'l' }, { 0 }, }; int opt; @@ -65,9 +64,6 @@ int main(int argc, char** argv) case 'c': cmdline = optarg; break; - case 'l': - loginuid = optarg; - break; default: usage: error_msg_and_die( @@ -77,7 +73,6 @@ int main(int argc, char** argv) " -p,--executable PATH absolute path to the program that crashed\n" " -u,--uuid UUID hash generated from the backtrace\n" " -c,--cmdline TEXT command line of the crashed program\n" - " -l,--loginuid UID login UID\n" ); } } @@ -112,8 +107,11 @@ int main(int argc, char** argv) dd.SaveText("cmdline", cmdline); if (uuid) dd.SaveText("uuid", uuid); - if (loginuid) - dd.SaveText("uid", loginuid); + + char uid[sizeof(int) * 3 + 2]; + sprintf(uid, "%d", (int)getuid()); + dd.SaveText("uid", uid); + dd.SaveText("backtrace", bt); free(bt); dd.Close(); diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in index 010bf12d..5514f1a4 100644 --- a/src/Hooks/abrt_exception_handler.py.in +++ b/src/Hooks/abrt_exception_handler.py.in @@ -114,7 +114,6 @@ def write_dump(pid, tb_uuid, tb): 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) |