If count item is missing in dump directory at abrtd start, then abrtd
considers that dump directory as unprocessed.
Closes #562
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/daemon/abrtd.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 111 insertions(+), 14 deletions(-)
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index 7001079..044eb41 100644
--- a/src/daemon/abrtd.c
+++ b/src/daemon/abrtd.c
@@ -892,6 +892,98 @@ static void start_syslog_logging()
putenv((char*)"ABRT_SYSLOG=1");
}
+/* The function expects that FILENAME_COUNT dump dir element is created by
+ * abrtd after all post-create events are successfully done. Thus if
+ * FILENAME_COUNT element doesn't exist abrtd can consider the dump directory
+ * as unprocessed.
+ *
+ * Relying on content of dump directory has one problem. If a hook provides
+ * FILENAME_COUNT abrtd will consider the dump directory as processed.
+ */
+static void mark_unprocessed_dump_dirs_not_reportable(const char *path)
+{
+ log("Searching for unprocessed dump directories");
+
+ DIR *dp = opendir(path);
+ if (!dp)
+ {
+ perror_msg("Can't find unprocessed dump directories in directory
'%s'", path);
+ return;
+ }
+
+ struct dirent *dent;
+ while ((dent = readdir(dp)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ char *full_name = concat_path_file(path, dent->d_name);
+
+ struct stat stat_buf;
+ if (stat(full_name, &stat_buf) != 0)
+ {
+ log("Can't access path '%s'", full_name);
+ goto next_dd;
+ }
+
+ if (S_ISDIR(stat_buf.st_mode) == 0)
+ /* This is expected. The dump location contains some aux files */
+ goto next_dd;
+
+ struct dump_dir *dd = dd_opendir(full_name, /*flags*/0);
+ if (dd)
+ {
+ if (!dd_exist(dd, FILENAME_COUNT))
+ {
+ log("Marking dump dir '%s' as not reportable because of
missing '"FILENAME_COUNT"' item",
+ full_name);
+
+ const char *reason = _("The problem data are incomplete. This
"
+ "usually happens when a problem is detected while
"
+ "computer is shutting down or user is logging out.
"
+ "In order to provide valuable problem reports, ABRT
"
+ "will not allow you to submit this problem. If you
"
+ "have time and want to help the developers in their
"
+ "effort to sort out this problem, please contact "
+ "them directly.");
+
+ /* Add dummy count 0 (valid dump directories has count >= 1)
+ * Doing it before updating FILENAME_NOT_REPORTABLE item in
+ * order to avoid unexpected growing of FILENAME_NOT_REPORTABLE
+ * item. And if any of the following operation will cause a
+ * failure of abrtd, then abrtd will not go there again after
+ * restart.
+ */
+ VERB1 log("Adding dummy count '0' to '%s'",
full_name);
+ dd_save_text(dd, FILENAME_COUNT, "0");
+
+ char *old_not_reportable = dd_load_text_ext(dd, FILENAME_NOT_REPORTABLE,
+ DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
+ if (old_not_reportable)
+ { /* Add the reason to the beginnig of
+ * FILENAME_NOT_REPORTABLE item because this has higher
+ * priority (two new lines because the reason doesn't
+ * have any)
+ */
+ char *message = xasprintf("%s\n\n%s", reason,
old_not_reportable);
+ dd_save_text(dd, FILENAME_NOT_REPORTABLE, message);
+ free(message);
+ free(old_not_reportable);
+ }
+ else
+ dd_save_text(dd, FILENAME_NOT_REPORTABLE, reason);
+ }
+ dd_close(dd);
+ }
+ else
+ log("Found an invalid dump directory '%s'", full_name);
+
+ next_dd:
+ free(full_name);
+ }
+ closedir(dp);
+}
+
int main(int argc, char** argv)
{
/* I18n */
@@ -959,6 +1051,25 @@ int main(int argc, char** argv)
if (s_timeout != 0)
signal(SIGALRM, handle_signal);
+ /* Moved before daemonization because parent waits for signal from daemon
+ * only for short period and time consumed by
+ * mark_unprocessed_dump_dirs_not_reportable() is slightly unpredictable.
+ */
+ GMainLoop* pMainloop = NULL;
+ GIOChannel* channel_inotify = NULL;
+ guint channel_id_inotify_event = 0;
+ GIOChannel* channel_signal = NULL;
+ guint channel_id_signal_event = 0;
+ bool pidfile_created = false;
+
+ /* Initialization */
+ VERB1 log("Loading settings");
+ if (load_abrt_conf() != 0)
+ goto init_error;
+
+ sanitize_dump_dir_rights();
+ mark_unprocessed_dump_dirs_not_reportable(g_settings_dump_location);
+
/* Daemonize unless -d */
if (!(opts & OPT_d))
{
@@ -994,20 +1105,6 @@ int main(int argc, char** argv)
start_syslog_logging();
}
- GMainLoop* pMainloop = NULL;
- GIOChannel* channel_inotify = NULL;
- guint channel_id_inotify_event = 0;
- GIOChannel* channel_signal = NULL;
- guint channel_id_signal_event = 0;
- bool pidfile_created = false;
-
- /* Initialization */
- VERB1 log("Loading settings");
- if (load_abrt_conf() != 0)
- goto init_error;
-
- sanitize_dump_dir_rights();
-
VERB1 log("Creating glib main loop");
pMainloop = g_main_loop_new(NULL, FALSE);
--
1.8.1.4