From 2ea5e514437af0e99cd66296797e4829bb601d43 Mon Sep 17 00:00:00 2001 From: Tim Pepper Date: Fri, 14 Sep 2012 17:07:02 -0700 Subject: [PATCH] Add some tentative duplicate handling The corewatcher needs to be ratelimited a bit for extremely crashy applications. For example mate's marco will respawn as much as a hundred times in a second. In the case of two cores within the same second the existing code collides in the hash table, so simply note that and unlink the core file which is under processing currently instead of erroring back up the stack to the main loop. Do similarly for core files which match within two characters at the end of the filename (ie: same time mod 100 seconds). This does have a bug though as the sent core is also being unlinked instead of persisting, but it's a crude start anyway. Still needs refining and also the space needs tmp watched. Signed-off-by: Tim Pepper --- src/coredump.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/src/coredump.c b/src/coredump.c index df9e70c..190938e 100644 --- a/src/coredump.c +++ b/src/coredump.c @@ -206,18 +206,59 @@ char *strip_directories(char *fullpath) /* * Move corefile from core_folder to processed_folder subdir. + * If this type of core has recently been seen, unlink this more recent + * example in order to rate limit submissions of extremely crashy + * applications. * Add extension if given and attempt to create directories if needed. */ int move_core(char *fullpath, char *extension) { - char *corefilename = NULL, newpath[8192]; + char *corefilename = NULL, newpath[8192], *coreprefix = NULL; + char *s = NULL; + size_t prefix_len; + DIR *dir = NULL; + struct dirent *entry = NULL; if (!fullpath) return -1; - if (!(corefilename = strip_directories(fullpath))) { - unlink(fullpath); + if (!(corefilename = strip_directories(fullpath))) return -ENOMEM; + + /* if the corefile's name minus any suffixes (such as .$PID) and + * minus two additional characters (ie: last two digits of + * timestamp assuming core_%e_%t) matches another core file in the + * processed_folder, simply unlink it instead of processing it for + * submission. TODO: consider a (configurable) time delta greater + * than which the cores must be separated, stat'ing the files, etc. + */ + if (!(coreprefix = strdup(corefilename))) + return -ENOMEM; + if (!(s = strstr(coreprefix, "."))) + return -1; + *s = '\0'; + prefix_len = strlen(coreprefix); + if (prefix_len > 2) { + s = strndup(coreprefix, prefix_len - 2); + free(coreprefix); + coreprefix = s; + } else { + goto error; + } + dir = opendir(processed_folder); + if (!dir) + goto error; + while(1) { + entry = readdir(dir); + if (!entry || !entry->d_name) + break; + if (entry->d_name[0] == '.') + continue; + if (!strstr(entry->d_name, coreprefix)) + continue; + fprintf(stderr, "+ ...ignoring/unlinking %s\n", fullpath); + unlink(fullpath); + goto error; } if (extension) @@ -225,10 +266,15 @@ int move_core(char *fullpath, char *extension) else snprintf(newpath, 8192, "%s%s", processed_folder, corefilename); + free(coreprefix); free(corefilename); rename(fullpath, newpath); return 0; +error: + free(coreprefix); + free(corefilename); + return -1; } /* @@ -442,10 +488,12 @@ static void write_core_detail_file(char *filename, char *text) return; if ((fd = open(detail_filename, O_WRONLY | O_CREAT | O_TRUNC, 0)) != -1) { - if(write(fd, text, strlen(text)) >= 0) + if(write(fd, text, strlen(text)) >= 0) { fchmod(fd, 0644); - else + } else { + fprintf(stderr, "+ ...ignoring/unlinking %s\n", detail_filename); unlink(detail_filename); + } close(fd); } free(detail_filename); @@ -680,6 +728,11 @@ static int add_to_processing(char *fullpath) pthread_mutex_lock(&core_status.processing_mtx); if (g_hash_table_lookup(core_status.processing_oops, c2)) { pthread_mutex_unlock(&core_status.processing_mtx); + /* This should only happen when the same core happened + * multiple times in the same second. Go ahead and + * ignore/remove the newer one here */ + fprintf(stderr, "+ ...ignoring/unlinking %s\n", fullpath); + unlink(fullpath); goto clean_add_to_processing; } @@ -786,6 +839,7 @@ int scan_corefolders(void __unused *unused) appfile = get_appfile(fullpath); if (!appfile) { + fprintf(stderr, "+ ...ignoring/unlinking %s\n", fullpath); unlink(fullpath); } else { free(appfile); -- 2.7.4