diff options
author | Zdenek Prikryl <zprikryl@redhat.com> | 2009-03-19 18:25:55 +0100 |
---|---|---|
committer | Zdenek Prikryl <zprikryl@redhat.com> | 2009-03-19 18:25:55 +0100 |
commit | 40cfd5a94bccd49742674037a339c179f2da2f24 (patch) | |
tree | 80abbc2780efc016bd1d60f84c4857d160793c54 | |
parent | 67fae29284030d4beca7d9176d3a6c09ae51363a (diff) | |
download | abrt-40cfd5a94bccd49742674037a339c179f2da2f24.tar.gz abrt-40cfd5a94bccd49742674037a339c179f2da2f24.tar.xz abrt-40cfd5a94bccd49742674037a339c179f2da2f24.zip |
new approach for getting debuginfos and backtraces
-rw-r--r-- | lib/MiddleWare/MiddleWare.cpp | 10 | ||||
-rw-r--r-- | lib/Plugins/CCpp.cpp | 221 | ||||
-rw-r--r-- | lib/Plugins/CCpp.h | 2 |
3 files changed, 172 insertions, 61 deletions
diff --git a/lib/MiddleWare/MiddleWare.cpp b/lib/MiddleWare/MiddleWare.cpp index e6e23020..66d6f78d 100644 --- a/lib/MiddleWare/MiddleWare.cpp +++ b/lib/MiddleWare/MiddleWare.cpp @@ -189,7 +189,15 @@ void CMiddleWare::CreateReport(const std::string& pUUID, dd.Open(row.m_sDebugDumpDir); dd.LoadText(FILENAME_ANALYZER, analyzer); - CreateReport(analyzer, row.m_sDebugDumpDir); + try + { + CreateReport(analyzer, row.m_sDebugDumpDir); + } + catch (...) + { + dd.Close(); + throw; + } UUID = GetGlobalUUID(analyzer, row.m_sDebugDumpDir); dd.SaveText(FILENAME_UUID, UUID); diff --git a/lib/Plugins/CCpp.cpp b/lib/Plugins/CCpp.cpp index 024ed1b9..2eb1cead 100644 --- a/lib/Plugins/CCpp.cpp +++ b/lib/Plugins/CCpp.cpp @@ -21,64 +21,129 @@ #include "CCpp.h" #include <fstream> -#include <ctype.h> #include "DebugDump.h" #include "Settings.h" #include <sstream> #include <iostream> #include <hash_map> +#include <ctype.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> #define CORE_PATTERN_IFACE "/proc/sys/kernel/core_pattern" #define CORE_PATTERN "|"CCPP_HOOK_PATH" %p %s" -#define DEBUGINFO_COMMAND "debuginfo-install -y " -#define GDB_COMMAND "gdb -batch -x " - CAnalyzerCCpp::CAnalyzerCCpp() : m_bMemoryMap(false) {} void CAnalyzerCCpp::InstallDebugInfos(const std::string& pPackage) { - char line[1024]; - std::string command = DEBUGINFO_COMMAND + pPackage; - std::string packageName = pPackage.substr(0, pPackage.rfind("-", pPackage.rfind("-") - 1)); - std::string packageERV = pPackage.substr(packageName.length()); - std::string packageDebuginfo = packageName+"-debuginfo"+packageERV; - std::string installed = "already installed and latest version"; - std::string canNotInstall = "No debuginfo packages available to install"; - FILE *fp = popen(command.c_str(), "r"); - - if (fp == NULL) + char buff[1024]; + int pipein[2], pipeout[2]; + struct timeval delay; + fd_set rsfd; + pid_t child; + + pipe(pipein); + pipe(pipeout); + + fcntl(pipein[0], F_SETFD, FD_CLOEXEC); + fcntl(pipeout[1], F_SETFD, FD_CLOEXEC); + + child = fork(); + if (child < 0) { - throw std::string("CAnalyzerCCpp::InstallDebugInfos(): cannot execute " + command) ; + throw std::string("CAnalyzerCCpp::RunGdb(): fork failed."); } - while (fgets(line, sizeof(line), fp)) + if (child == 0) { - std::string text = line; - std::cout << text; - if (text.find(packageDebuginfo) != std::string::npos && - text.find(installed) != std::string::npos) - { - pclose(fp); - return; - } - if (text.find(canNotInstall) != std::string::npos) - { - pclose(fp); - throw std::string("CAnalyzerCCpp::InstallDebugInfos(): cannot install debuginfos for " + pPackage + " (" + canNotInstall + ")") ; - } + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + dup2(pipein[0], STDIN_FILENO); + close(pipein[0]); + dup2(pipeout[1], STDOUT_FILENO); + close(pipeout[1]); + + setsid(); + execlp("debuginfo-install", "debuginfo-install", pPackage.c_str(), NULL); + exit(0); } - if (pclose(fp) != 0) + + close(pipein[0]); + close(pipeout[1]); + + bool quit = false; + + while(!quit) { - throw std::string("CAnalyzerCCpp::InstallDebugInfos(): cannot install debuginfos for " + pPackage) ; + FD_ZERO(&rsfd); + + FD_SET(pipeout[0], &rsfd); + + delay.tv_sec = 1; + delay.tv_usec = 0; + + if(select(FD_SETSIZE, &rsfd, NULL, NULL, &delay) > 0) + { + if(FD_ISSET(pipeout[0], &rsfd)) + { + int r = read(pipeout[0], buff, sizeof(buff)); + if (r <= 0) + { + quit = true; + } + else + { + buff[r] = '\0'; + std::cerr << buff; + if (strstr(buff, "already installed and latest version") != NULL) + { + break; + } + if (strstr(buff, "No debuginfo packages available to install") != NULL || + strstr(buff, "Could not find debuginfo for main pkg") != NULL || + strstr(buff, "Could not find debuginfo pkg for dependency package") != NULL) + { + close(pipein[1]); + close(pipeout[0]); + kill(child, SIGTERM); + wait(NULL); + throw std::string("CAnalyzerCCpp::InstallDebugInfos(): cannot install debuginfos for ") + pPackage; + } + if (strstr(buff, "Total download size") != NULL) + { + int r = write(pipein[1], "y\n", sizeof("y\n")); + if (r != sizeof("y\n")) + { + close(pipein[1]); + close(pipeout[0]); + kill(child, SIGTERM); + wait(NULL); + throw std::string("CAnalyzerCCpp::InstallDebugInfos(): cannot install debuginfos for ") + pPackage; + } + } + } + } + } } + close(pipein[1]); + close(pipeout[0]); + + wait(NULL); } void CAnalyzerCCpp::GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktrace) { std::string tmpFile = "/tmp/" + pDebugDumpDir.substr(pDebugDumpDir.rfind("/")); std::ofstream fTmp; + std::string UID; fTmp.open(tmpFile.c_str()); if (fTmp.is_open()) { @@ -86,6 +151,7 @@ void CAnalyzerCCpp::GetBacktrace(const std::string& pDebugDumpDir, std::string& CDebugDump dd; dd.Open(pDebugDumpDir); dd.LoadText(FILENAME_EXECUTABLE, executable); + dd.LoadText(FILENAME_UID, UID); dd.Close(); fTmp << "file " << executable << std::endl; fTmp << "core " << pDebugDumpDir << "/" << FILENAME_BINARYDATA1 << std::endl; @@ -97,8 +163,8 @@ void CAnalyzerCCpp::GetBacktrace(const std::string& pDebugDumpDir, std::string& { throw "CAnalyzerCCpp::GetBacktrace(): cannot create gdb script " + tmpFile ; } - std::string command = GDB_COMMAND + tmpFile; - RunCommand(command, pBacktrace); + + RunGdb(tmpFile, UID, pBacktrace); } void CAnalyzerCCpp::GetIndependentBacktrace(const std::string& pBacktrace, std::string& pIndependentBacktrace) @@ -144,24 +210,70 @@ void CAnalyzerCCpp::GetIndependentBacktrace(const std::string& pBacktrace, std:: } } -void CAnalyzerCCpp::RunCommand(const std::string& pCommand, std::string& pOutput) +void CAnalyzerCCpp::RunGdb(const std::string& pScript, const std::string pUID, std::string& pOutput) { - char line[1024]; - std::string output; - FILE *fp = popen(pCommand.c_str(), "r"); - if (fp == NULL) + int pipeout[2]; + char buff[1024]; + struct timeval delay; + fd_set rsfd; + pid_t child; + + pipe(pipeout); + fcntl(pipeout[1], F_SETFD, FD_CLOEXEC); + + child = fork(); + if (child == -1) { - throw "CAnalyzerCCpp::GetBacktrace(): cannot execute " + pCommand ; + throw std::string("CAnalyzerCCpp::RunGdb(): fork failed."); } - pOutput = ""; - while (fgets(line, 1024, fp) != NULL) + if(child == 0) { - output += line; + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + dup2(pipeout[1], STDOUT_FILENO); + close(pipeout[1]); + + setuid(atoi(pUID.c_str())); + seteuid(atoi(pUID.c_str())); + setsid(); + + execlp("gdb", "gdb","-batch", "-x", pScript.c_str(), NULL); + exit(0); } - pOutput = output; + close(pipeout[1]); + + bool quit = false; + + while(!quit) + { + FD_ZERO(&rsfd); + FD_SET(pipeout[0], &rsfd); - pclose(fp); + delay.tv_sec = 1; + delay.tv_usec = 0; + + if(select(FD_SETSIZE, &rsfd, NULL, NULL, &delay) > 0) + { + if(FD_ISSET(pipeout[0], &rsfd)) + { + int r = read(pipeout[0], buff, sizeof(buff)); + if (r <= 0) + { + quit = true; + } + else + { + buff[r] = '\0'; + pOutput += buff; + } + } + } + } + close(pipeout[0]); + wait(NULL); } std::string CAnalyzerCCpp::GetLocalUUID(const std::string& pDebugDumpDir) @@ -211,22 +323,13 @@ void CAnalyzerCCpp::CreateReport(const std::string& pDebugDumpDir) return; } dd.LoadText(FILENAME_PACKAGE, package); - try - { - InstallDebugInfos(package); - } - catch(std::string& err) - { - dd.Close(); - throw err; - } - catch(...) - { - std::cerr << "generic catch..." << std::endl; - dd.Close(); - throw std::string("error"); - } + dd.Close(); + + InstallDebugInfos(package); + GetBacktrace(pDebugDumpDir, backtrace); + + dd.Open(pDebugDumpDir); dd.SaveText(FILENAME_TEXTDATA1, backtrace); if (m_bMemoryMap) { diff --git a/lib/Plugins/CCpp.h b/lib/Plugins/CCpp.h index e89d7000..9a946597 100644 --- a/lib/Plugins/CCpp.h +++ b/lib/Plugins/CCpp.h @@ -35,7 +35,7 @@ class CAnalyzerCCpp : public CAnalyzer void InstallDebugInfos(const std::string& pPackage); void GetBacktrace(const std::string& pDebugDumpDir, std::string& pBacktrace); void GetIndependentBacktrace(const std::string& pBacktrace, std::string& pIndependentBacktrace); - void RunCommand(const std::string&pCommand, std::string& pOutput); + void RunGdb(const std::string& pScript, const std::string pUID, std::string& pOutput); public: CAnalyzerCCpp(); |