#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/statvfs.h>
+#include <syslog.h>
#include <dirent.h>
#include <glib.h>
#include <errno.h>
* race where the condition is set before the thread is awaiting it and
* thus is not woken.
*/
-static GMutex pq_mtx;
+GMutex *pq_mtx;
static gboolean pq = FALSE;
-static GCond pq_work;
+GCond *pq_work;
+
+static int diskfree = 100;
static char *get_release(void)
{
fprintf(stderr, "+ extract_core() called for %s\n", fullpath);
- if (asprintf(&command, "LANG=C gdb --batch -f %s %s -x /etc/corewatcher/gdb.command 2> /dev/null", appfile, fullpath) == -1)
+ if (asprintf(&command, "LANG=C gdb --batch -f '%s' '%s' -x /etc/corewatcher/gdb.command 2> /dev/null", appfile, fullpath) == -1)
return NULL;
file = popen(command, "r");
"maps: |\n"
"%s",
h1,
- c1 ? c1 : " Unknown",
- m1 ? m1 : " Unknown");
+ c1 ? c1 : " Unknown\n",
+ m1 ? m1 : " Unknown\n");
free(h1);
if (c1)
free(c1);
}
fprintf(stderr, "+ Begin scanning %s...\n", core_folder);
while(1) {
- free(fullpath);
- fullpath = NULL;
-
entry = readdir(dir);
if (!entry || !entry->d_name)
break;
ret = move_core(fullpath, "to-process");
if (ret == 0)
work++;
+
+ free(fullpath);
+ fullpath = NULL;
}
closedir(dir);
if (work) {
fprintf(stderr, "+ Found %d files, setting pq_work condition\n", work);
- g_mutex_lock(&pq_mtx);
- g_cond_signal(&pq_work);
+ g_mutex_lock(pq_mtx);
+ g_cond_signal(pq_work);
pq = TRUE;
- g_mutex_unlock(&pq_mtx);
+ g_mutex_unlock(pq_mtx);
}
fprintf(stderr, "+ End scanning %s...\n", core_folder);
struct oops *oops = NULL;
while(1) {
- g_mutex_lock(&pq_mtx);
+ g_mutex_lock(pq_mtx);
while (pq != TRUE) {
fprintf(stderr, "+ Awaiting work in %s...\n", processed_folder);
- g_cond_wait(&pq_work, &pq_mtx);
+ g_cond_wait(pq_work, pq_mtx);
}
pq = FALSE;
- g_mutex_unlock(&pq_mtx);
+ g_mutex_unlock(pq_mtx);
fprintf(stderr, "+ Begin scanning %s...\n", processed_folder);
return NULL;
}
+static void disable_corefiles(int diskfree)
+{
+ int ret;
+ ret = system("echo \"\" > /proc/sys/kernel/core_pattern");
+ if (ret != -1) {
+ fprintf(stderr, "+ disabled core pattern, disk low %d%%\n", diskfree);
+ syslog(LOG_WARNING,
+ "Disabled kernel core_pattern, %s only has %d%% available",
+ core_folder, diskfree);
+ }
+}
+
+void enable_corefiles(int diskfree)
+{
+ int ret;
+ char * proc_core_string = NULL;
+ ret = asprintf(&proc_core_string,
+ "echo \"%score_%%e_%%t\" > /proc/sys/kernel/core_pattern",
+ core_folder);
+ if (ret == -1)
+ goto err;
+
+ ret = system(proc_core_string);
+ free(proc_core_string);
+ if (ret == -1)
+ goto err;
+
+ if (diskfree == -1) {
+ fprintf(stderr, "+ enabled core pattern\n");
+ syslog(LOG_INFO, "Enabled corewatcher kernel core_pattern\n");
+ } else {
+ fprintf(stderr, "+ reenabled core pattern, disk %d%%", diskfree);
+ syslog(LOG_WARNING,
+ "Reenabled corewatcher kernel core_pattern, %s now has %d%% available",
+ core_folder, diskfree);
+ }
+ return;
+err:
+ fprintf(stderr, "+ unable to enable core pattern\n");
+ syslog(LOG_WARNING, "Unable to enable kernel core_pattern\n");
+ return;
+}
+
/* do everything, called from timer event */
int scan_folders(void __unused *unused)
{
+ struct statvfs stat;
+ int newdiskfree;
+
+ if (statvfs(core_folder, &stat) == 0) {
+ newdiskfree = (int)(100 * stat.f_bavail / stat.f_blocks);
+
+ openlog("corewatcher", 0, LOG_KERN);
+ if ((newdiskfree < 10) && (diskfree >= 10))
+ disable_corefiles(newdiskfree);
+ if ((newdiskfree > 12) && (diskfree <= 12))
+ enable_corefiles(newdiskfree);
+ closelog();
+
+ diskfree = newdiskfree;
+ }
+
scan_core_folder(NULL);
- g_mutex_lock(&pq_mtx);
- g_cond_signal(&pq_work);
+ g_mutex_lock(pq_mtx);
+ g_cond_signal(pq_work);
pq = TRUE;
- g_mutex_unlock(&pq_mtx);
+ g_mutex_unlock(pq_mtx);
return TRUE;
}