/* rhbz#539551: "abrt going crazy when crashing process is respawned". * Check total size of problem dirs, if it overflows, * delete oldest/biggest dirs. */ void trim_problem_dirs(const char *dirname, double cap_size, const char *exclude_path) { const char *excluded_basename = NULL; if (exclude_path) { unsigned len_dirname = strlen(dirname); /* Trim trailing '/'s, but dont trim name "/" to "" */ while (len_dirname > 1 && dirname[len_dirname-1] == '/') len_dirname--; if (strncmp(dirname, exclude_path, len_dirname) == 0 && exclude_path[len_dirname] == '/' ) { /* exclude_path is "dirname/something" */ excluded_basename = exclude_path + len_dirname + 1; } } log_debug("excluded_basename:'%s'", excluded_basename); int count = 20; while (--count >= 0) { /* We exclude our own dir from candidates for deletion (3rd param): */ char *worst_basename = NULL; double cur_size = get_dirsize_find_largest_dir(dirname, &worst_basename, excluded_basename); if (cur_size <= cap_size || !worst_basename) { log_info("cur_size:%.0f cap_size:%.0f, no (more) trimming", cur_size, cap_size); free(worst_basename); break; } log("%s is %.0f bytes (more than %.0fMiB), deleting '%s'", dirname, cur_size, cap_size / (1024*1024), worst_basename); char *d = concat_path_file(dirname, worst_basename); free(worst_basename); delete_dump_dir(d); free(d); } }
/* Queueing the process will also lead to cleaning up the dump location. */ static void queue_post_craete_process(struct abrt_server_proc *proc) { load_abrt_conf(); struct abrt_server_proc *running = s_dir_queue == NULL ? NULL : (struct abrt_server_proc *)s_dir_queue->data; if (g_settings_nMaxCrashReportsSize == 0) goto consider_processing; const char *full_path_ignored = running != NULL ? running->dirname : proc->dirname; const char *ignored = strrchr(full_path_ignored, '/'); if (NULL == ignored) /* Paranoia, this should not happen. */ ignored = full_path_ignored; else /* Move behind '/' */ ++ignored; char *worst_dir = NULL; const double max_size = 1024 * 1024 * g_settings_nMaxCrashReportsSize; while (get_dirsize_find_largest_dir(g_settings_dump_location, &worst_dir, ignored) >= max_size && worst_dir) { const char *kind = "old"; GList *proc_of_deleted_item = NULL; if (proc != NULL && strcmp(worst_dir, proc->dirname) == 0) { kind = "new"; stop_abrt_server(proc); proc = NULL; } else if ((proc_of_deleted_item = g_list_find_custom(s_dir_queue, worst_dir, (GCompareFunc)abrt_server_compare_dirname))) { kind = "unprocessed"; struct abrt_server_proc *removed_proc = (struct abrt_server_proc *)proc_of_deleted_item->data; s_dir_queue = g_list_delete_link(s_dir_queue, proc_of_deleted_item); stop_abrt_server(removed_proc); } log_warning("Size of '%s' >= %u MB (MaxCrashReportsSize), deleting %s directory '%s'", g_settings_dump_location, g_settings_nMaxCrashReportsSize, kind, worst_dir); char *deleted = concat_path_file(g_settings_dump_location, worst_dir); free(worst_dir); worst_dir = NULL; struct dump_dir *dd = dd_opendir(deleted, DD_FAIL_QUIETLY_ENOENT); if (dd != NULL) dd_delete(dd); free(deleted); } consider_processing: /* If the process survived cleaning up the dump location, append it to the * post-create queue. */ if (proc != NULL) s_dir_queue = g_list_append(s_dir_queue, proc); /* If there were no running post-crate process before we added the * currently handled process to the post-create queue, start processing of * the currently handled process. */ if (running == NULL) notify_next_post_create_process(NULL/*finished*/); }