summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2010-08-19 15:34:06 +0200
committerKarel Klic <kklic@redhat.com>2010-08-19 15:34:06 +0200
commite29e4bef382b5c4c768acf80a9fe89fae81752ae (patch)
tree33597b063e8f2a3b9ab099b468265b21f9336cd5
parent8f4b6e717f6bfec1f35ed2931a76a2793e76bef1 (diff)
parente4b94e60457254a50405be93ca63cf925dd934d7 (diff)
downloadabrt-e29e4bef382b5c4c768acf80a9fe89fae81752ae.tar.gz
abrt-e29e4bef382b5c4c768acf80a9fe89fae81752ae.tar.xz
abrt-e29e4bef382b5c4c768acf80a9fe89fae81752ae.zip
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
-rw-r--r--lib/plugins/Kerneloops.cpp201
-rw-r--r--lib/plugins/Kerneloops.h8
-rw-r--r--lib/plugins/KerneloopsReporter.cpp138
-rw-r--r--lib/plugins/KerneloopsReporter.h18
-rw-r--r--lib/plugins/KerneloopsScanner.h10
-rw-r--r--lib/plugins/KerneloopsSysLog.cpp664
6 files changed, 538 insertions, 501 deletions
diff --git a/lib/plugins/Kerneloops.cpp b/lib/plugins/Kerneloops.cpp
index 379197b2..2ffc2e34 100644
--- a/lib/plugins/Kerneloops.cpp
+++ b/lib/plugins/Kerneloops.cpp
@@ -25,117 +25,126 @@
static unsigned hash_oops_str(const char *oops_ptr)
{
- unsigned char old_c;
- unsigned char c = 0;
- unsigned hash = 0;
+ unsigned char old_c;
+ unsigned char c = 0;
+ unsigned hash = 0;
- /* Special-case: if the first line is of form:
- * WARNING: at net/wireless/core.c:614 wdev_cleanup_work+0xe9/0x120 [cfg80211]() (Not tainted)
- * then hash only "file:line func+ofs/len" part.
- */
- if (strncmp(oops_ptr, "WARNING: at ", sizeof("WARNING: at ")-1) == 0) {
- const char *p = oops_ptr + sizeof("WARNING: at ")-1;
- p = strchr(p, ' '); /* skip filename:NNN */
- if (p) {
- p = strchrnul(p + 1, ' '); /* skip function_name+0xNN/0xNNN */
- oops_ptr += sizeof("WARNING: at ")-1;
- while (oops_ptr < p) {
- c = *oops_ptr++;
- hash = ((hash << 5) ^ (hash >> 27)) ^ c;
- }
- return hash;
- }
- }
+ /* Special-case: if the first line is of form:
+ * WARNING: at net/wireless/core.c:614 wdev_cleanup_work+0xe9/0x120 [cfg80211]() (Not tainted)
+ * then hash only "file:line func+ofs/len" part.
+ */
+ if (strncmp(oops_ptr, "WARNING: at ", sizeof("WARNING: at ")-1) == 0)
+ {
+ const char *p = oops_ptr + sizeof("WARNING: at ")-1;
+ p = strchr(p, ' '); /* skip filename:NNN */
+ if (p)
+ {
+ p = strchrnul(p + 1, ' '); /* skip function_name+0xNN/0xNNN */
+ oops_ptr += sizeof("WARNING: at ")-1;
+ while (oops_ptr < p)
+ {
+ c = *oops_ptr++;
+ hash = ((hash << 5) ^ (hash >> 27)) ^ c;
+ }
+ return hash;
+ }
+ }
- while (1) {
- old_c = c;
- c = *oops_ptr++;
- if (!c)
- break;
- if (c == '\n') {
- // Exclude some lines which have process name - in some oops classes
- // process name is irrelevant and changes with every oops.
- // Lines we filter out:
- // Pid: 8003, comm: Xorg Not tainted (2.6.27.9-159.fc10.i686 #1)
- // Process Xorg (pid: 8003, ti=f0a0c000 task=f2380000 task.ti=f0a0c000)
- if (strncmp(oops_ptr, "Pid: ", 5) == 0
- || strncmp(oops_ptr, "Process ", 8) == 0
- ) {
- while (*oops_ptr && *oops_ptr != '\n')
- oops_ptr++;
- continue;
- }
- }
- if (!isalnum(old_c)) {
- if (c >= '0' && c <= '9') {
- // Convert all (possibly hex) numbers to just one '0'
- if (c == '0' && *oops_ptr == 'x') // "0xSOMETHING"
- oops_ptr++;
- while (isxdigit(*oops_ptr))
- oops_ptr++;
- c = '0';
- } else
- if ((c|0x20) >= 'a' && (c|0x20) <= 'f') {
- // This *may be* a hex number without 0x prefix: "f0a0c000"
- // Check that it indeed is, and replace with '0'
- const char *oops_ptr2 = oops_ptr;
- while (isxdigit(*oops_ptr2))
- oops_ptr2++;
- // Does it end in a letter which is not a hex digit?
- // (Example: "abcw" is not a hex number, "abc " is)
- if (!isalpha(*oops_ptr2)) {
- // It's "abc " case. Skip the "abc" string
- oops_ptr = oops_ptr2;
- c = '0';
- }
- // else: hash the string as-is
- }
- }
- // TODO: Drop call trace tail - in interrupt-driven oopses,
- // everything before interrupt is irrelevant.
- // Example of call trace part of oops:
- // Call Trace:
- // [<f88e11c7>] ? radeon_cp_resume+0x7d/0xbc [radeon]
- // [<f88745f8>] ? drm_ioctl+0x1b0/0x225 [drm]
- // [<f88e114a>] ? radeon_cp_resume+0x0/0xbc [radeon]
- // [<c049b1c0>] ? vfs_ioctl+0x50/0x69
- // [<c049b414>] ? do_vfs_ioctl+0x23b/0x247
- // [<c0460a56>] ? audit_syscall_entry+0xf9/0x123
- // [<c049b460>] ? sys_ioctl+0x40/0x5c
- // [<c0403c76>] ? syscall_call+0x7/0xb
+ while (1)
+ {
+ old_c = c;
+ c = *oops_ptr++;
+ if (!c)
+ break;
+ if (c == '\n')
+ {
+ // Exclude some lines which have process name - in some oops classes
+ // process name is irrelevant and changes with every oops.
+ // Lines we filter out:
+ // Pid: 8003, comm: Xorg Not tainted (2.6.27.9-159.fc10.i686 #1)
+ // Process Xorg (pid: 8003, ti=f0a0c000 task=f2380000 task.ti=f0a0c000)
+ if (strncmp(oops_ptr, "Pid: ", 5) == 0
+ || strncmp(oops_ptr, "Process ", 8) == 0
+ ) {
+ while (*oops_ptr && *oops_ptr != '\n')
+ oops_ptr++;
+ continue;
+ }
+ }
+ if (!isalnum(old_c))
+ {
+ if (c >= '0' && c <= '9')
+ {
+ // Convert all (possibly hex) numbers to just one '0'
+ if (c == '0' && *oops_ptr == 'x') // "0xSOMETHING"
+ oops_ptr++;
+ while (isxdigit(*oops_ptr))
+ oops_ptr++;
+ c = '0';
+ }
+ else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
+ {
+ // This *may be* a hex number without 0x prefix: "f0a0c000"
+ // Check that it indeed is, and replace with '0'
+ const char *oops_ptr2 = oops_ptr;
+ while (isxdigit(*oops_ptr2))
+ oops_ptr2++;
+ // Does it end in a letter which is not a hex digit?
+ // (Example: "abcw" is not a hex number, "abc " is)
+ if (!isalpha(*oops_ptr2))
+ {
+ // It's "abc " case. Skip the "abc" string
+ oops_ptr = oops_ptr2;
+ c = '0';
+ }
+ // else: hash the string as-is
+ }
+ }
+ // TODO: Drop call trace tail - in interrupt-driven oopses,
+ // everything before interrupt is irrelevant.
+ // Example of call trace part of oops:
+ // Call Trace:
+ // [<f88e11c7>] ? radeon_cp_resume+0x7d/0xbc [radeon]
+ // [<f88745f8>] ? drm_ioctl+0x1b0/0x225 [drm]
+ // [<f88e114a>] ? radeon_cp_resume+0x0/0xbc [radeon]
+ // [<c049b1c0>] ? vfs_ioctl+0x50/0x69
+ // [<c049b414>] ? do_vfs_ioctl+0x23b/0x247
+ // [<c0460a56>] ? audit_syscall_entry+0xf9/0x123
+ // [<c049b460>] ? sys_ioctl+0x40/0x5c
+ // [<c0403c76>] ? syscall_call+0x7/0xb
- /* An algorithm proposed by Donald E. Knuth in The Art Of Computer
- * Programming Volume 3, under the topic of sorting and search
- * chapter 6.4.
- */
- hash = ((hash << 5) ^ (hash >> 27)) ^ c;
- }
- return hash;
+ /* An algorithm proposed by Donald E. Knuth in The Art Of Computer
+ * Programming Volume 3, under the topic of sorting and search
+ * chapter 6.4.
+ */
+ hash = ((hash << 5) ^ (hash >> 27)) ^ c;
+ }
+ return hash;
}
std::string CAnalyzerKerneloops::GetLocalUUID(const char *pDebugDumpDir)
{
- VERB3 log("Getting local universal unique identification");
+ VERB3 log("Getting local universal unique identification");
- std::string oops;
- CDebugDump dd;
- if (!dd.Open(pDebugDumpDir))
- {
- VERB1 log(_("Unable to open debug dump '%s'"), pDebugDumpDir);
- return std::string("");
- }
+ std::string oops;
+ CDebugDump dd;
+ if (!dd.Open(pDebugDumpDir))
+ {
+ VERB1 log(_("Unable to open debug dump '%s'"), pDebugDumpDir);
+ return std::string("");
+ }
- dd.LoadText(FILENAME_BACKTRACE, oops);
+ dd.LoadText(FILENAME_BACKTRACE, oops);
- unsigned hash = hash_oops_str(oops.c_str());
- hash &= 0x7FFFFFFF;
+ unsigned hash = hash_oops_str(oops.c_str());
+ hash &= 0x7FFFFFFF;
- return to_string(hash);
+ return to_string(hash);
}
std::string CAnalyzerKerneloops::GetGlobalUUID(const char *pDebugDumpDir)
{
- return GetLocalUUID(pDebugDumpDir);
+ return GetLocalUUID(pDebugDumpDir);
}
PLUGIN_INFO(ANALYZER,
diff --git a/lib/plugins/Kerneloops.h b/lib/plugins/Kerneloops.h
index 2160f444..cac2c526 100644
--- a/lib/plugins/Kerneloops.h
+++ b/lib/plugins/Kerneloops.h
@@ -33,10 +33,10 @@
class CAnalyzerKerneloops : public CAnalyzer
{
- public:
- virtual std::string GetLocalUUID(const char *pDebugDumpDir);
- virtual std::string GetGlobalUUID(const char *pDebugDumpDir);
- virtual void CreateReport(const char *pDebugDumpDir, int force) {}
+ public:
+ virtual std::string GetLocalUUID(const char *pDebugDumpDir);
+ virtual std::string GetGlobalUUID(const char *pDebugDumpDir);
+ virtual void CreateReport(const char *pDebugDumpDir, int force) {}
};
#endif
diff --git a/lib/plugins/KerneloopsReporter.cpp b/lib/plugins/KerneloopsReporter.cpp
index 2b4df3a0..3af8a932 100644
--- a/lib/plugins/KerneloopsReporter.cpp
+++ b/lib/plugins/KerneloopsReporter.cpp
@@ -26,105 +26,107 @@
/* helpers */
static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
- size *= nmemb;
+ size *= nmemb;
/*
- char *c, *c1, *c2;
-
- log("received: '%*.*s'\n", (int)size, (int)size, (char*)ptr);
- c = (char*)xzalloc(size + 1);
- memcpy(c, ptr, size);
- c1 = strstr(c, "201 ");
- if (c1) {
- c1 += 4;
- c2 = strchr(c1, '\n');
- if (c2)
- *c2 = 0;
- }
- free(c);
+ char *c, *c1, *c2;
+
+ log("received: '%*.*s'\n", (int)size, (int)size, (char*)ptr);
+ c = (char*)xzalloc(size + 1);
+ memcpy(c, ptr, size);
+ c1 = strstr(c, "201 ");
+ if (c1)
+ {
+ c1 += 4;
+ c2 = strchr(c1, '\n');
+ if (c2)
+ *c2 = 0;
+ }
+ free(c);
*/
- return size;
+ return size;
}
/* Send oops data to kerneloops.org-style site, using HTTP POST */
/* Returns 0 on success */
static CURLcode http_post_to_kerneloops_site(const char *url, const char *oopsdata)
{
- CURLcode ret;
- CURL *handle;
- struct curl_httppost *post = NULL;
- struct curl_httppost *last = NULL;
+ CURLcode ret;
+ CURL *handle;
+ struct curl_httppost *post = NULL;
+ struct curl_httppost *last = NULL;
- handle = xcurl_easy_init();
- curl_easy_setopt(handle, CURLOPT_URL, url);
+ handle = xcurl_easy_init();
+ curl_easy_setopt(handle, CURLOPT_URL, url);
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "oopsdata",
- CURLFORM_COPYCONTENTS, oopsdata,
- CURLFORM_END);
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "pass_on_allowed",
- CURLFORM_COPYCONTENTS, "yes",
- CURLFORM_END);
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "oopsdata",
+ CURLFORM_COPYCONTENTS, oopsdata,
+ CURLFORM_END);
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "pass_on_allowed",
+ CURLFORM_COPYCONTENTS, "yes",
+ CURLFORM_END);
- curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
- curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction);
+ curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writefunction);
- ret = curl_easy_perform(handle);
+ ret = curl_easy_perform(handle);
- curl_formfree(post);
- curl_easy_cleanup(handle);
+ curl_formfree(post);
+ curl_easy_cleanup(handle);
- return ret;
+ return ret;
}
/* class CKerneloopsReporter */
CKerneloopsReporter::CKerneloopsReporter() :
- m_sSubmitURL("http://submit.kerneloops.org/submitoops.php")
+ m_sSubmitURL("http://submit.kerneloops.org/submitoops.php")
{}
std::string CKerneloopsReporter::Report(const map_crash_data_t& pCrashData,
const map_plugin_settings_t& pSettings,
const char *pArgs)
{
- CURLcode ret;
-
- update_client(_("Creating and submitting a report..."));
-
- map_crash_data_t::const_iterator it = pCrashData.find(FILENAME_BACKTRACE);
- if (it != pCrashData.end()) {
- ret = http_post_to_kerneloops_site(
- m_sSubmitURL.c_str(),
- it->second[CD_CONTENT].c_str()
- );
- }
-
- if (ret != CURLE_OK) {
- char* err_str = xasprintf("Kernel oops has not been sent due to %s", curl_easy_strerror(ret));
- CABRTException e(EXCEP_PLUGIN, err_str);
- free(err_str);
- throw e;
- }
- /* Server replies with:
- * 200 thank you for submitting the kernel oops information
- * RemoteIP: 34192fd15e34bf60fac6a5f01bba04ddbd3f0558
- * - no URL or bug ID apparently...
- */
- return "Kernel oops report was uploaded";
+ CURLcode ret;
+
+ update_client(_("Creating and submitting a report..."));
+
+ map_crash_data_t::const_iterator it = pCrashData.find(FILENAME_BACKTRACE);
+ if (it != pCrashData.end())
+ {
+ ret = http_post_to_kerneloops_site(
+ m_sSubmitURL.c_str(),
+ it->second[CD_CONTENT].c_str()
+ );
+ }
+
+ if (ret != CURLE_OK)
+ {
+ char* err_str = xasprintf("Kernel oops has not been sent due to %s", curl_easy_strerror(ret));
+ CABRTException e(EXCEP_PLUGIN, err_str);
+ free(err_str);
+ throw e;
+ }
+ /* Server replies with:
+ * 200 thank you for submitting the kernel oops information
+ * RemoteIP: 34192fd15e34bf60fac6a5f01bba04ddbd3f0558
+ * - no URL or bug ID apparently...
+ */
+ return "Kernel oops report was uploaded";
}
void CKerneloopsReporter::SetSettings(const map_plugin_settings_t& pSettings)
{
- m_pSettings = pSettings;
-
- map_plugin_settings_t::const_iterator end = pSettings.end();
- map_plugin_settings_t::const_iterator it;
- it = pSettings.find("SubmitURL");
- if (it != end) {
- m_sSubmitURL = it->second;
- }
+ m_pSettings = pSettings;
+
+ map_plugin_settings_t::const_iterator end = pSettings.end();
+ map_plugin_settings_t::const_iterator it;
+ it = pSettings.find("SubmitURL");
+ if (it != end)
+ m_sSubmitURL = it->second;
}
//ok to delete?
diff --git a/lib/plugins/KerneloopsReporter.h b/lib/plugins/KerneloopsReporter.h
index cb939d0d..679e5b0b 100644
--- a/lib/plugins/KerneloopsReporter.h
+++ b/lib/plugins/KerneloopsReporter.h
@@ -34,18 +34,18 @@
class CKerneloopsReporter : public CReporter
{
- private:
- std::string m_sSubmitURL;
+ private:
+ std::string m_sSubmitURL;
- public:
- CKerneloopsReporter();
+ public:
+ CKerneloopsReporter();
- virtual void SetSettings(const map_plugin_settings_t& pSettings);
+ virtual void SetSettings(const map_plugin_settings_t& pSettings);
//ok to delete?
-// virtual const map_plugin_settings_t& GetSettings();
- virtual std::string Report(const map_crash_data_t& pCrashData,
- const map_plugin_settings_t& pSettings,
- const char *pArgs);
+// virtual const map_plugin_settings_t& GetSettings();
+ virtual std::string Report(const map_crash_data_t& pCrashData,
+ const map_plugin_settings_t& pSettings,
+ const char *pArgs);
};
#endif
diff --git a/lib/plugins/KerneloopsScanner.h b/lib/plugins/KerneloopsScanner.h
index 0904146e..2bddb0f4 100644
--- a/lib/plugins/KerneloopsScanner.h
+++ b/lib/plugins/KerneloopsScanner.h
@@ -32,11 +32,11 @@
class CKerneloopsScanner : public CAction
{
-private:
- time_t m_syslog_last_change;
-public:
- CKerneloopsScanner();
- virtual void Run(const char *pActionDir, const char *pArgs, int force);
+ private:
+ time_t m_syslog_last_change;
+ public:
+ CKerneloopsScanner();
+ virtual void Run(const char *pActionDir, const char *pArgs, int force);
};
#endif
diff --git a/lib/plugins/KerneloopsSysLog.cpp b/lib/plugins/KerneloopsSysLog.cpp
index 66cce416..8fdd1ac7 100644
--- a/lib/plugins/KerneloopsSysLog.cpp
+++ b/lib/plugins/KerneloopsSysLog.cpp
@@ -23,7 +23,7 @@
static void queue_oops(vector_string_t &vec, const char *data, const char *version)
{
- vec.push_back(ssprintf("%s\n%s", version, data));
+ vec.push_back(ssprintf("%s\n%s", version, data));
}
/*
@@ -31,336 +31,362 @@ static void queue_oops(vector_string_t &vec, const char *data, const char *versi
*/
static int extract_version(const char *linepointer, char *version)
{
- int ret;
-
- ret = 0;
- if (strstr(linepointer, "Pid")
- || strstr(linepointer, "comm")
- || strstr(linepointer, "CPU")
- || strstr(linepointer, "REGS")
- || strstr(linepointer, "EFLAGS")
- ) {
- char* start;
- char* end;
-
- start = strstr((char*)linepointer, "2.6.");
- if (start) {
- end = strchr(start, ')');
- if (!end)
- end = strchrnul(start, ' ');
- strncpy(version, start, end-start);
- ret = 1;
- }
- }
-
- if (!ret)
- strncpy(version, "undefined", 9);
-
- return ret;
+ int ret;
+
+ ret = 0;
+ if (strstr(linepointer, "Pid")
+ || strstr(linepointer, "comm")
+ || strstr(linepointer, "CPU")
+ || strstr(linepointer, "REGS")
+ || strstr(linepointer, "EFLAGS")
+ ) {
+ char* start;
+ char* end;
+
+ start = strstr((char*)linepointer, "2.6.");
+ if (start)
+ {
+ end = strchr(start, ')');
+ if (!end)
+ end = strchrnul(start, ' ');
+ strncpy(version, start, end-start);
+ ret = 1;
+ }
+ }
+
+ if (!ret)
+ strncpy(version, "undefined", 9);
+
+ return ret;
}
/*
* extract_oops tries to find oops signatures in a log
*/
struct line_info {
- char *ptr;
- char level;
+ char *ptr;
+ char level;
};
+
static int record_oops(vector_string_t &oopses, struct line_info* lines_info, int oopsstart, int oopsend)
{
- int q;
- int len;
- int is_version;
- char *oops;
- char *version;
-
- len = 2;
- for (q = oopsstart; q <= oopsend; q++)
- len += strlen(lines_info[q].ptr) + 1;
-
- oops = (char*)xzalloc(len);
- version = (char*)xzalloc(len);
-
- is_version = 0;
- for (q = oopsstart; q <= oopsend; q++) {
- if (!is_version)
- is_version = extract_version(lines_info[q].ptr, version);
- if (lines_info[q].ptr[0]) {
- strcat(oops, lines_info[q].ptr);
- strcat(oops, "\n");
- }
- }
- int rv = 1;
- /* too short oopses are invalid */
- if (strlen(oops) > 100) {
- queue_oops(oopses, oops, version);
- } else {
- VERB3 log("Dropped oops: too short");
- rv = 0;
- }
- free(oops);
- free(version);
- return rv;
+ int q;
+ int len;
+ int is_version;
+ char *oops;
+ char *version;
+
+ len = 2;
+ for (q = oopsstart; q <= oopsend; q++)
+ len += strlen(lines_info[q].ptr) + 1;
+
+ oops = (char*)xzalloc(len);
+ version = (char*)xzalloc(len);
+
+ is_version = 0;
+ for (q = oopsstart; q <= oopsend; q++)
+ {
+ if (!is_version)
+ is_version = extract_version(lines_info[q].ptr, version);
+
+ if (lines_info[q].ptr[0])
+ {
+ strcat(oops, lines_info[q].ptr);
+ strcat(oops, "\n");
+ }
+ }
+ int rv = 1;
+ /* too short oopses are invalid */
+ if (strlen(oops) > 100)
+ queue_oops(oopses, oops, version);
+ else
+ {
+ VERB3 log("Dropped oops: too short");
+ rv = 0;
+ }
+ free(oops);
+ free(version);
+ return rv;
}
#define REALLOC_CHUNK 1000
int extract_oopses(vector_string_t &oopses, char *buffer, size_t buflen)
{
- char *c;
- int linecount = 0;
- int lines_info_alloc = 0;
- struct line_info *lines_info = NULL;
-
- /* Split buffer into lines */
-
- if (buflen != 0)
- buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */
- c = buffer;
- while (c < buffer + buflen) {
- char linelevel;
- char *c9;
- char *colon;
-
- c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */
- assert(c9);
- *c9 = '\0'; /* turn the \n into a string termination */
- if (c9 == c)
- goto next_line;
-
- /* Is it a syslog file (/var/log/messages or similar)?
- * Even though _usually_ it looks like "Nov 19 12:34:38 localhost kernel: xxx",
- * some users run syslog in non-C locale:
- * "2010-02-22T09:24:08.156534-08:00 gnu-4 gnome-session[2048]: blah blah"
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!!
- * We detect it by checking for N:NN:NN pattern in first 15 chars
- * (and this still is not good enough... false positive: "pci 0000:15:00.0: PME# disabled")
- */
- colon = strchr(c, ':');
- if (colon && colon > c && colon < c + 15
- && isdigit(colon[-1]) /* N:... */
- && isdigit(colon[1]) /* ...N:NN:... */
- && isdigit(colon[2])
- && colon[3] == ':'
- && isdigit(colon[4]) /* ...N:NN:NN... */
- && isdigit(colon[5])
- ) {
- /* It's syslog file, not a bare dmesg */
-
- /* Skip non-kernel lines */
- char *kernel_str = strstr(c, "kernel: ");
- if (kernel_str == NULL) {
- /* if we see our own marker:
- * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt"
- * we know we submitted everything upto here already */
- if (strstr(c, "abrt:") && strstr(c, "Abrt")) {
- VERB3 log("Found our marker at line %d, restarting line count from 0", linecount);
- linecount = 0;
- lines_info_alloc = 0;
- free(lines_info);
- lines_info = NULL;
- }
- goto next_line;
- }
- c = kernel_str + sizeof("kernel: ")-1;
- }
-
- linelevel = 0;
- /* store and remove kernel log level */
- if (*c == '<' && c[1] && c[2] == '>') {
- linelevel = c[1];
- c += 3;
- }
- /* remove jiffies time stamp counter if present */
- if (*c == '[') {
- char *c2 = strchr(c, '.');
- char *c3 = strchr(c, ']');
- if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8) {
- c = c3 + 1;
- if (*c == ' ')
- c++;
- }
- }
- if (linecount >= lines_info_alloc) {
- lines_info_alloc += REALLOC_CHUNK;
- lines_info = (line_info*)xrealloc(lines_info,
- lines_info_alloc * sizeof(struct line_info));
- }
- lines_info[linecount].ptr = c;
- lines_info[linecount].level = linelevel;
- linecount++;
+ char *c;
+ int linecount = 0;
+ int lines_info_alloc = 0;
+ struct line_info *lines_info = NULL;
+
+ /* Split buffer into lines */
+
+ if (buflen != 0)
+ buffer[buflen - 1] = '\n'; /* the buffer usually ends with \n, but let's make sure */
+ c = buffer;
+ while (c < buffer + buflen)
+ {
+ char linelevel;
+ char *c9;
+ char *colon;
+
+ c9 = (char*)memchr(c, '\n', buffer + buflen - c); /* a \n will always be found */
+ assert(c9);
+ *c9 = '\0'; /* turn the \n into a string termination */
+ if (c9 == c)
+ goto next_line;
+
+ /* Is it a syslog file (/var/log/messages or similar)?
+ * Even though _usually_ it looks like "Nov 19 12:34:38 localhost kernel: xxx",
+ * some users run syslog in non-C locale:
+ * "2010-02-22T09:24:08.156534-08:00 gnu-4 gnome-session[2048]: blah blah"
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!!
+ * We detect it by checking for N:NN:NN pattern in first 15 chars
+ * (and this still is not good enough... false positive: "pci 0000:15:00.0: PME# disabled")
+ */
+ colon = strchr(c, ':');
+ if (colon && colon > c && colon < c + 15
+ && isdigit(colon[-1]) /* N:... */
+ && isdigit(colon[1]) /* ...N:NN:... */
+ && isdigit(colon[2])
+ && colon[3] == ':'
+ && isdigit(colon[4]) /* ...N:NN:NN... */
+ && isdigit(colon[5])
+ ) {
+ /* It's syslog file, not a bare dmesg */
+
+ /* Skip non-kernel lines */
+ char *kernel_str = strstr(c, "kernel: ");
+ if (kernel_str == NULL)
+ {
+ /* if we see our own marker:
+ * "hostname abrt: Kerneloops: Reported 1 kernel oopses to Abrt"
+ * we know we submitted everything upto here already */
+ if (strstr(c, "abrt:") && strstr(c, "Abrt"))
+ {
+ VERB3 log("Found our marker at line %d, restarting line count from 0", linecount);
+ linecount = 0;
+ lines_info_alloc = 0;
+ free(lines_info);
+ lines_info = NULL;
+ }
+ goto next_line;
+ }
+ c = kernel_str + sizeof("kernel: ")-1;
+ }
+
+ linelevel = 0;
+ /* store and remove kernel log level */
+ if (*c == '<' && c[1] && c[2] == '>')
+ {
+ linelevel = c[1];
+ c += 3;
+ }
+ /* remove jiffies time stamp counter if present */
+ if (*c == '[')
+ {
+ char *c2 = strchr(c, '.');
+ char *c3 = strchr(c, ']');
+ if (c2 && c3 && (c2 < c3) && (c3-c) < 14 && (c2-c) < 8)
+ {
+ c = c3 + 1;
+ if (*c == ' ')
+ c++;
+ }
+ }
+ if (linecount >= lines_info_alloc)
+ {
+ lines_info_alloc += REALLOC_CHUNK;
+ lines_info = (line_info*)xrealloc(lines_info,
+ lines_info_alloc * sizeof(struct line_info));
+ }
+ lines_info[linecount].ptr = c;
+ lines_info[linecount].level = linelevel;
+ linecount++;
next_line:
- c = c9 + 1;
- }
-
- /* Analyze lines */
-
- int i;
- char prevlevel = 0;
- int oopsstart = -1;
- int inbacktrace = 0;
- int oopsesfound = 0;
-
- i = 0;
- while (i < linecount) {
- char *curline = lines_info[i].ptr;
-
- if (curline == NULL) {
- i++;
- continue;
- }
- while (*curline == ' ')
- curline++;
-
- if (oopsstart < 0) {
- /* find start-of-oops markers */
- if (strstr(curline, "general protection fault:"))
- oopsstart = i;
- else if (strstr(curline, "BUG:"))
- oopsstart = i;
- else if (strstr(curline, "kernel BUG at"))
- oopsstart = i;
- else if (strstr(curline, "do_IRQ: stack overflow:"))
- oopsstart = i;
- else if (strstr(curline, "RTNL: assertion failed"))
- oopsstart = i;
- else if (strstr(curline, "Eeek! page_mapcount(page) went negative!"))
- oopsstart = i;
- else if (strstr(curline, "near stack overflow (cur:"))
- oopsstart = i;
- else if (strstr(curline, "double fault:"))
- oopsstart = i;
- else if (strstr(curline, "Badness at"))
- oopsstart = i;
- else if (strstr(curline, "NETDEV WATCHDOG"))
- oopsstart = i;
- else if (strstr(curline, "WARNING: at ")) /* WARN_ON() generated message */
- oopsstart = i;
- else if (strstr(curline, "Unable to handle kernel"))
- oopsstart = i;
- else if (strstr(curline, "sysctl table check failed"))
- oopsstart = i;
- else if (strstr(curline, "INFO: possible recursive locking detected"))
- oopsstart = i;
- // Not needed: "--[ cut here ]--" is always followed
- // by "Badness at", "kernel BUG at", or "WARNING: at" string
- //else if (strstr(curline, "------------[ cut here ]------------"))
- // oopsstart = i;
- else if (strstr(curline, "list_del corruption."))
- oopsstart = i;
- else if (strstr(curline, "list_add corruption."))
- oopsstart = i;
- if (strstr(curline, "Oops:") && i >= 3)
- oopsstart = i-3;
-
- if (oopsstart >= 0) {
- /* debug information */
- VERB3 {
- log("Found oops at line %d: '%s'", oopsstart, lines_info[oopsstart].ptr);
- if (oopsstart != i)
- log("Trigger line is %d: '%s'", i, c);
- }
- /* try to find the end marker */
- int i2 = i + 1;
- while (i2 < linecount && i2 < (i+50)) {
- if (strstr(lines_info[i2].ptr, "---[ end trace")) {
- inbacktrace = 1;
- i = i2;
- break;
- }
- i2++;
- }
- }
- }
-
- /* Are we entering a call trace part? */
- /* a call trace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */
- if (oopsstart >= 0 && !inbacktrace) {
- if (strstr(curline, "Call Trace:"))
- inbacktrace = 1;
- else
- if (strnlen(curline, 9) > 8
- && curline[0] == '[' && curline[1] == '<'
- && strstr(curline, ">]")
- && strstr(curline, "+0x")
- && strstr(curline, "/0x")
- ) {
- inbacktrace = 1;
- }
- }
-
- /* Are we at the end of an oops? */
- else if (oopsstart >= 0 && inbacktrace) {
- int oopsend = INT_MAX;
-
- /* line needs to start with " [" or have "] [" if it is still a call trace */
- /* example: "[<ffffffffa006c156>] radeon_get_ring_head+0x16/0x41 [radeon]" */
- if (curline[0] != '['
- && !strstr(curline, "] [")
- && !strstr(curline, "--- Exception")
- && !strstr(curline, "LR =")
- && !strstr(curline, "<#DF>")
- && !strstr(curline, "<IRQ>")
- && !strstr(curline, "<EOI>")
- && !strstr(curline, "<<EOE>>")
- && strncmp(curline, "Code: ", 6) != 0
- && strncmp(curline, "RIP ", 4) != 0
- && strncmp(curline, "RSP ", 4) != 0
- ) {
- oopsend = i-1; /* not a call trace line */
- }
- /* oops lines are always more than 8 chars long */
- else if (strnlen(curline, 8) < 8)
- oopsend = i-1;
- /* single oopses are of the same loglevel */
- else if (lines_info[i].level != prevlevel)
- oopsend = i-1;
- else if (strstr(curline, "Instruction dump:"))
- oopsend = i;
- /* if a new oops starts, this one has ended */
- else if (strstr(curline, "WARNING: at ") && oopsstart != i) /* WARN_ON() generated message */
- oopsend = i-1;
- else if (strstr(curline, "Unable to handle") && oopsstart != i)
- oopsend = i-1;
- /* kernel end-of-oops marker (not including marker itself) */
- else if (strstr(curline, "---[ end trace"))
- oopsend = i-1;
-
- if (oopsend <= i) {
- VERB3 log("End of oops at line %d (%d): '%s'", oopsend, i, lines_info[oopsend].ptr);
- if (record_oops(oopses, lines_info, oopsstart, oopsend))
- oopsesfound++;
- oopsstart = -1;
- inbacktrace = 0;
- }
- }
-
- prevlevel = lines_info[i].level;
- i++;
-
- if (oopsstart >= 0) {
- /* Do we have a suspiciously long oops? Cancel it */
- if (i-oopsstart > 60) {
- inbacktrace = 0;
- oopsstart = -1;
- VERB3 log("Dropped oops, too long");
- continue;
- }
- if (!inbacktrace && i-oopsstart > 40) {
- /*inbacktrace = 0; - already is */
- oopsstart = -1;
- VERB3 log("Dropped oops, too long");
- continue;
- }
- }
- } /* while (i < linecount) */
-
- /* process last oops if we have one */
- if (oopsstart >= 0 && inbacktrace) {
- int oopsend = i-1;
- VERB3 log("End of oops at line %d (end of file): '%s'", oopsend, lines_info[oopsend].ptr);
- if (record_oops(oopses, lines_info, oopsstart, oopsend))
- oopsesfound++;
- }
-
- free(lines_info);
- return oopsesfound;
+ c = c9 + 1;
+ }
+
+ /* Analyze lines */
+
+ int i;
+ char prevlevel = 0;
+ int oopsstart = -1;
+ int inbacktrace = 0;
+ int oopsesfound = 0;
+
+ i = 0;
+ while (i < linecount)
+ {
+ char *curline = lines_info[i].ptr;
+
+ if (curline == NULL)
+ {
+ i++;
+ continue;
+ }
+ while (*curline == ' ')
+ curline++;
+
+ if (oopsstart < 0)
+ {
+ /* find start-of-oops markers */
+ if (strstr(curline, "general protection fault:"))
+ oopsstart = i;
+ else if (strstr(curline, "BUG:"))
+ oopsstart = i;
+ else if (strstr(curline, "kernel BUG at"))
+ oopsstart = i;
+ else if (strstr(curline, "do_IRQ: stack overflow:"))
+ oopsstart = i;
+ else if (strstr(curline, "RTNL: assertion failed"))
+ oopsstart = i;
+ else if (strstr(curline, "Eeek! page_mapcount(page) went negative!"))
+ oopsstart = i;
+ else if (strstr(curline, "near stack overflow (cur:"))
+ oopsstart = i;
+ else if (strstr(curline, "double fault:"))
+ oopsstart = i;
+ else if (strstr(curline, "Badness at"))
+ oopsstart = i;
+ else if (strstr(curline, "NETDEV WATCHDOG"))
+ oopsstart = i;
+ else if (strstr(curline, "WARNING: at ")) /* WARN_ON() generated message */
+ oopsstart = i;
+ else if (strstr(curline, "Unable to handle kernel"))
+ oopsstart = i;
+ else if (strstr(curline, "sysctl table check failed"))
+ oopsstart = i;
+ else if (strstr(curline, "INFO: possible recursive locking detected"))
+ oopsstart = i;
+ // Not needed: "--[ cut here ]--" is always followed
+ // by "Badness at", "kernel BUG at", or "WARNING: at" string
+ //else if (strstr(curline, "------------[ cut here ]------------"))
+ // oopsstart = i;
+ else if (strstr(curline, "list_del corruption."))
+ oopsstart = i;
+ else if (strstr(curline, "list_add corruption."))
+ oopsstart = i;
+ if (strstr(curline, "Oops:") && i >= 3)
+ oopsstart = i-3;
+
+ if (oopsstart >= 0)
+ {
+ /* debug information */
+ VERB3 {
+ log("Found oops at line %d: '%s'", oopsstart, lines_info[oopsstart].ptr);
+ if (oopsstart != i)
+ log("Trigger line is %d: '%s'", i, c);
+ }
+ /* try to find the end marker */
+ int i2 = i + 1;
+ while (i2 < linecount && i2 < (i+50))
+ {
+ if (strstr(lines_info[i2].ptr, "---[ end trace"))
+ {
+ inbacktrace = 1;
+ i = i2;
+ break;
+ }
+ i2++;
+ }
+ }
+ }
+
+ /* Are we entering a call trace part? */
+ /* a call trace starts with "Call Trace:" or with the " [<.......>] function+0xFF/0xAA" pattern */
+ if (oopsstart >= 0 && !inbacktrace)
+ {
+ if (strstr(curline, "Call Trace:"))
+ inbacktrace = 1;
+ else
+ if (strnlen(curline, 9) > 8
+ && curline[0] == '[' && curline[1] == '<'
+ && strstr(curline, ">]")
+ && strstr(curline, "+0x")
+ && strstr(curline, "/0x")
+ ) {
+ inbacktrace = 1;
+ }
+ }
+
+ /* Are we at the end of an oops? */
+ else if (oopsstart >= 0 && inbacktrace)
+ {
+ int oopsend = INT_MAX;
+
+ /* line needs to start with " [" or have "] [" if it is still a call trace */
+ /* example: "[<ffffffffa006c156>] radeon_get_ring_head+0x16/0x41 [radeon]" */
+ if (curline[0] != '['
+ && !strstr(curline, "] [")
+ && !strstr(curline, "--- Exception")
+ && !strstr(curline, "LR =")
+ && !strstr(curline, "<#DF>")
+ && !strstr(curline, "<IRQ>")
+ && !strstr(curline, "<EOI>")
+ && !strstr(curline, "<<EOE>>")
+ && strncmp(curline, "Code: ", 6) != 0
+ && strncmp(curline, "RIP ", 4) != 0
+ && strncmp(curline, "RSP ", 4) != 0
+ ) {
+ oopsend = i-1; /* not a call trace line */
+ }
+ /* oops lines are always more than 8 chars long */
+ else if (strnlen(curline, 8) < 8)
+ oopsend = i-1;
+ /* single oopses are of the same loglevel */
+ else if (lines_info[i].level != prevlevel)
+ oopsend = i-1;
+ else if (strstr(curline, "Instruction dump:"))
+ oopsend = i;
+ /* if a new oops starts, this one has ended */
+ else if (strstr(curline, "WARNING: at ") && oopsstart != i) /* WARN_ON() generated message */
+ oopsend = i-1;
+ else if (strstr(curline, "Unable to handle") && oopsstart != i)
+ oopsend = i-1;
+ /* kernel end-of-oops marker (not including marker itself) */
+ else if (strstr(curline, "---[ end trace"))
+ oopsend = i-1;
+
+ if (oopsend <= i)
+ {
+ VERB3 log("End of oops at line %d (%d): '%s'", oopsend, i, lines_info[oopsend].ptr);
+ if (record_oops(oopses, lines_info, oopsstart, oopsend))
+ oopsesfound++;
+ oopsstart = -1;
+ inbacktrace = 0;
+ }
+ }
+
+ prevlevel = lines_info[i].level;
+ i++;
+
+ if (oopsstart >= 0)
+ {
+ /* Do we have a suspiciously long oops? Cancel it */
+ if (i-oopsstart > 60)
+ {
+ inbacktrace = 0;
+ oopsstart = -1;
+ VERB3 log("Dropped oops, too long");
+ continue;
+ }
+ if (!inbacktrace && i-oopsstart > 40)
+ {
+ /*inbacktrace = 0; - already is */
+ oopsstart = -1;
+ VERB3 log("Dropped oops, too long");
+ continue;
+ }
+ }
+ } /* while (i < linecount) */
+
+ /* process last oops if we have one */
+ if (oopsstart >= 0 && inbacktrace)
+ {
+ int oopsend = i-1;
+ VERB3 log("End of oops at line %d (end of file): '%s'", oopsend, lines_info[oopsend].ptr);
+ if (record_oops(oopses, lines_info, oopsstart, oopsend))
+ oopsesfound++;
+ }
+
+ free(lines_info);
+ return oopsesfound;
}