summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorZdenek Prikryl <zdeny@dhcp-lab-218.englab.brq.redhat.com>2009-05-12 15:39:08 +0200
committerZdenek Prikryl <zdeny@dhcp-lab-218.englab.brq.redhat.com>2009-05-12 15:39:08 +0200
commit099ae27f9a2b374aedbfa3b75925b8f6ba475b45 (patch)
tree4571dd79362b24ceb6a7b2b6f66548a02a2a8ba4 /lib
parentc720d6077b907f944573cd09fd84503b592c1526 (diff)
downloadabrt-099ae27f9a2b374aedbfa3b75925b8f6ba475b45.tar.gz
abrt-099ae27f9a2b374aedbfa3b75925b8f6ba475b45.tar.xz
abrt-099ae27f9a2b374aedbfa3b75925b8f6ba475b45.zip
new scanner, it is used by abrt's cron
Diffstat (limited to 'lib')
-rw-r--r--lib/Plugins/KerneloopsScanner.conf (renamed from lib/Plugins/Kerneloops.conf)2
-rw-r--r--lib/Plugins/KerneloopsScanner.cpp159
-rw-r--r--lib/Plugins/KerneloopsScanner.h38
3 files changed, 198 insertions, 1 deletions
diff --git a/lib/Plugins/Kerneloops.conf b/lib/Plugins/KerneloopsScanner.conf
index 0022711..36aac09 100644
--- a/lib/Plugins/Kerneloops.conf
+++ b/lib/Plugins/KerneloopsScanner.conf
@@ -1,4 +1,4 @@
-# Kerneloops configuration.
+# Kerneloops Scanner configuration.
################################################################################
SysLogFile = /var/log/messages
diff --git a/lib/Plugins/KerneloopsScanner.cpp b/lib/Plugins/KerneloopsScanner.cpp
new file mode 100644
index 0000000..05e2a18
--- /dev/null
+++ b/lib/Plugins/KerneloopsScanner.cpp
@@ -0,0 +1,159 @@
+#include "KerneloopsScanner.h"
+#include "DebugDump.h"
+#include "ABRTException.h"
+#include "CommLayerInner.h"
+#include "PluginSettings.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <asm/unistd.h>
+
+
+#define MAX(A,B) ((A) > (B) ? (A) : (B))
+#define FILENAME_KERNELOOPS "kerneloops"
+
+void CKerneloopsScanner::WriteSysLog(int m_nCount)
+{
+ if (m_nCount > 0) {
+ openlog("abrt", 0, LOG_KERN);
+ syslog(LOG_WARNING, "Kerneloops: Reported %i kernel oopses to Abrt", m_nCount);
+ closelog();
+ }
+}
+
+void CKerneloopsScanner::Run(const std::string& pActionDir,
+ const std::string& pArgs)
+{
+ ScanDmesg();
+ if (!m_bSysLogFileScanned)
+ {
+ ScanSysLogFile(m_sSysLogFile.c_str(), 1);
+ m_bSysLogFileScanned = true;
+ }
+}
+
+void CKerneloopsScanner::SaveOopsToDebugDump()
+{
+ comm_layer_inner_status("Creating kernel oops crash reports...");
+
+ CDebugDump m_pDebugDump;
+ char m_sPath[PATH_MAX];
+ std::list<COops> m_pOopsList;
+
+ time_t t = time(NULL);
+ if (((time_t) -1) == t)
+ {
+ throw CABRTException(EXCEP_PLUGIN, "CAnalyzerKerneloops::Report(): cannot get local time.");
+ }
+
+ m_pOopsList = m_pSysLog.GetOopsList();
+ m_pSysLog.ClearOopsList();
+ while (!m_pOopsList.empty())
+ {
+ snprintf(m_sPath, sizeof(m_sPath), "%s/kerneloops-%d-%d", DEBUG_DUMPS_DIR, t, m_pOopsList.size());
+
+ COops m_pOops;
+ m_pOops = m_pOopsList.back();
+
+ try
+ {
+ m_pDebugDump.Create(m_sPath);
+ m_pDebugDump.SaveText(FILENAME_ANALYZER, "Kerneloops");
+ m_pDebugDump.SaveText(FILENAME_UID, "0");
+ m_pDebugDump.SaveText(FILENAME_EXECUTABLE, "kernel");
+ m_pDebugDump.SaveText(FILENAME_KERNEL, m_pOops.m_sVersion);
+ m_pDebugDump.SaveText(FILENAME_PACKAGE, "not_applicable");
+ m_pDebugDump.SaveText(FILENAME_KERNELOOPS, m_pOops.m_sData);
+ m_pDebugDump.Close();
+ }
+ catch (CABRTException& e)
+ {
+ throw CABRTException(EXCEP_PLUGIN, "CAnalyzerKerneloops::Report(): " + e.what());
+ }
+ m_pOopsList.pop_back();
+ }
+}
+
+
+void CKerneloopsScanner::ScanDmesg()
+{
+ comm_layer_inner_debug("Scanning dmesg...");
+
+ int m_nFoundOopses;
+ char *buffer;
+
+ buffer = (char*)calloc(getpagesize()+1, 1);
+
+ syscall(__NR_syslog, 3, buffer, getpagesize());
+ m_nFoundOopses = m_pSysLog.ExtractOops(buffer, strlen(buffer), 0);
+ free(buffer);
+
+ if (m_nFoundOopses > 0)
+ SaveOopsToDebugDump();
+}
+
+void CKerneloopsScanner::ScanSysLogFile(const char *filename, int issyslog)
+{
+ comm_layer_inner_debug("Scanning syslog...");
+
+ char *buffer;
+ struct stat statb;
+ FILE *file;
+ int ret;
+ int m_nFoundOopses;
+ size_t buflen;
+
+ memset(&statb, 0, sizeof(statb));
+
+ ret = stat(filename, &statb);
+
+ if (statb.st_size < 1 || ret != 0)
+ return;
+
+ /*
+ * in theory there's a race here, since someone could spew
+ * to /var/log/messages before we read it in... we try to
+ * deal with it by reading at most 1023 bytes extra. If there's
+ * more than that.. any oops will be in dmesg anyway.
+ * Do not try to allocate an absurt amount of memory; ignore
+ * older log messages because they are unlikely to have
+ * sufficiently recent data to be useful. 32MB is more
+ * than enough; it's not worth looping through more log
+ * if the log is larger than that.
+ */
+ buflen = MAX(statb.st_size+1024, 32*1024*1024);
+ buffer = (char*)calloc(buflen, 1);
+ assert(buffer != NULL);
+
+ file = fopen(filename, "rm");
+ if (!file) {
+ free(buffer);
+ return;
+ }
+ fseek(file, -buflen, SEEK_END);
+ ret = fread(buffer, 1, buflen-1, file);
+ fclose(file);
+
+ if (ret > 0)
+ m_nFoundOopses = m_pSysLog.ExtractOops(buffer, buflen-1, issyslog);
+ free(buffer);
+
+ if (m_nFoundOopses > 0) {
+ SaveOopsToDebugDump();
+ WriteSysLog(m_nFoundOopses);
+ }
+}
+
+void CKerneloopsScanner::LoadSettings(const std::string& pPath)
+{
+ map_settings_t settings;
+ plugin_load_settings(pPath, settings);
+
+ if (settings.find("SysLogFile")!= settings.end())
+ {
+ m_sSysLogFile = settings["SysLogFile"];
+ }
+}
diff --git a/lib/Plugins/KerneloopsScanner.h b/lib/Plugins/KerneloopsScanner.h
new file mode 100644
index 0000000..f823d1f
--- /dev/null
+++ b/lib/Plugins/KerneloopsScanner.h
@@ -0,0 +1,38 @@
+#ifndef KERNELOOPSSCANNER_H_
+#define KERNELOOPSSCANNER_H_
+
+#include "KerneloopsSysLog.h"
+#include "Plugin.h"
+#include "Action.h"
+
+class CKerneloopsScanner : public CAction
+{
+ private:
+ std::string m_sSysLogFile;
+ CSysLog m_pSysLog;
+ bool m_bSysLogFileScanned;
+
+ void SaveOopsToDebugDump();
+ void ScanDmesg();
+ void ScanSysLogFile(const char *filename, int issyslog);
+ void WriteSysLog(int m_nCount);
+ public:
+ CKerneloopsScanner() :
+ m_sSysLogFile("/var/log/messages"),
+ m_bSysLogFileScanned(false)
+ {}
+ virtual ~CKerneloopsScanner() {}
+ virtual void Run(const std::string& pActionDir,
+ const std::string& pArgs);
+ virtual void LoadSettings(const std::string& pPath);
+};
+
+PLUGIN_INFO(ACTION,
+ CKerneloopsScanner,
+ "KerneloopsScanner",
+ "0.0.1",
+ "Save new Kerneloops crashes into debug dump dir",
+ "anton@redhat.com",
+ "http://people.redhat.com/aarapov");
+
+#endif /* KERNELOOPSSCANNER_H_ */