ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/debug/Debugger.cpp
Revision: 1491
Committed: Mon Aug 16 18:05:58 2010 UTC (14 years, 8 months ago) by chuckv
File size: 5401 byte(s)
Log Message:
Adding debugging and tracing tools from protomol to openmd.

File Contents

# User Rev Content
1 chuckv 1490 /*******************************************************************\
2    
3     Copyright (C) 2004 Joseph Coffland
4    
5     This program is free software; you can redistribute it and/or
6     modify it under the terms of the GNU General Public License
7     as published by the Free Software Foundation; either version 2
8     of the License, or (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18     02111-1307, USA.
19    
20     For information regarding this software email
21     jcofflan@users.sourceforge.net
22    
23     \*******************************************************************/
24    
25 chuckv 1491 #include "utils/Exception.hpp"
26 chuckv 1490
27     #ifdef HAVE_DEBUGGER
28 chuckv 1491 #include "debug/Debugger.hpp"
29     #include "debug/Process.hpp"
30     //#include "type/String.h"
31 chuckv 1490
32     #include <sys/time.h>
33     #include <sys/resource.h>
34     #include <unistd.h>
35     #include <sys/types.h>
36     #include <sys/wait.h>
37     #include <sys/stat.h>
38     #include <fcntl.h>
39     #include <stdlib.h>
40     #include <stdio.h>
41    
42     #include <sstream>
43    
44     using namespace std;
45 chuckv 1491 using namespace OpenMD;
46 chuckv 1490
47     string Debugger::executableName;
48     int Debugger::numTraces = 0;
49     bool Debugger::traceFiltering = true;
50     int Debugger::maxTraces = 10;
51    
52     void Debugger::initStackTrace(string executableName) {
53     Debugger::executableName = executableName;
54     Exception::enableStackTraces = true;
55     }
56    
57     bool Debugger::printStackTrace(ostream &stream) {
58     trace_t trace;
59     bool retVal = getStackTrace(trace);
60    
61     trace_t::iterator it;
62     for (it = trace.begin(); it != trace.end(); it++)
63     stream << *it << endl;
64    
65     return retVal;
66     }
67    
68     #define BUF_SIZE 2048
69    
70     bool Debugger::_getStackTrace(trace_t &trace) {
71     if (executableName == "") {
72     trace.push_back("Stack Trace Error: Stack dumper not initialized!");
73     return false;
74     }
75    
76     numTraces++;
77     if (maxTraces && numTraces > maxTraces) {
78     trace.push_back("Stack Trace Error: Exceeded maxTraces of " +
79     String(maxTraces));
80     return false;
81     }
82    
83     // Spawn gdb process
84     int argc = 0;
85     const char *argv[5];
86    
87     argv[argc++] = "gdb";
88     argv[argc++] = (char *)executableName.c_str();
89     String pid(getpid());
90     argv[argc++] = (char *)pid.c_str();
91     argv[argc] = 0;
92    
93     try {
94     Process debugProc;
95     Pipe *inPipe = debugProc.getChildPipe(Process::TO_CHILD, 0);
96     Pipe *outPipe = debugProc.getChildPipe(Process::FROM_CHILD, 1);
97     Pipe *errPipe = debugProc.getChildPipe(Process::FROM_CHILD, 2);
98    
99     // Run gdb commands
100     string debugCmd =
101     string("set width ") + String(BUF_SIZE - 1) + "\nwhere\nquit\n";
102     ssize_t size =
103     write(inPipe->getInFD(), debugCmd.c_str(), debugCmd.length());
104     size = size;
105    
106     // Execute debugger process
107     debugProc.exec((char **)argv);
108    
109     // Read output
110     FILE *out = fdopen(outPipe->getOutFD(), "r");
111     FILE *err = fdopen(errPipe->getOutFD(), "r");
112     if (!out || !err) {
113     trace.push_back("Stack Trace Error: Opening debugger output streams!");
114    
115     return false;
116     }
117    
118     char buf[BUF_SIZE + 1];
119     int offset = 0;
120     int count = 0;
121     while (fgets(buf, BUF_SIZE, out))
122     if (buf[0] == '#') {
123     if (traceFiltering) {
124     count++;
125    
126     if (strstr(buf, "Debugger::") ||
127     strstr(buf, "Exception::init") ||
128     strstr(buf, "Exception (")) {
129     offset = count;
130     trace.clear();
131     continue;
132     }
133     }
134    
135     int line = atoi(&buf[1]) - offset;
136     char *start = strchr(buf, ' ');
137     int len = strlen(buf);
138    
139     if (buf[len - 1] == '\n' || buf[len - 1] == '\r') buf[len - 1] = 0;
140     trace.push_back(string("#") + String(line) + start);
141     }
142    
143     #ifdef DEBUGGER_PRINT_ERROR_STREAM
144     while (fgets(buf, BUF_SIZE, err)) {
145     int len = strlen(buf);
146     if (buf[len - 1] == '\n' || buf[len - 1] == '\r') buf[len - 1] = 0;
147     if (buf[0] != 0) trace.push_back(buf);
148     }
149     #endif
150    
151    
152     // Clean up
153     fclose(out);
154     fclose(err);
155    
156     debugProc.wait();
157     if (debugProc.getReturnCode()) {
158     trace.push_back("Stack Trace Error: gdb returned an error.");
159    
160     return false;
161     }
162    
163     return true;
164     } catch (const Exception &e) {
165     trace.push_back(string("Stack Trace Error: ") + e.getMessage());
166     }
167    
168     return false;
169     }
170    
171     bool Debugger::getStackTrace(trace_t &trace) {
172     static bool inStackTrace = false;
173     bool ret;
174    
175     if (inStackTrace) {
176     trace.push_back("Stack Trace Error: Already in stack trace!");
177     return false;
178     }
179    
180     inStackTrace = true;
181    
182     try {
183     ret = _getStackTrace(trace);
184     } catch (...) {
185     inStackTrace = false;
186     throw;
187     }
188     inStackTrace = false;
189    
190     return ret;
191     }
192     #endif // HAVE_DEBUGGER
193    
194     #ifdef DEBUGGER_TEST
195     #include <iostream>
196    
197     void b(int x) {
198     THROW("Test cause!");
199     }
200    
201     void a(char *x) {
202     try {
203     b(10);
204     } catch (const Exception &e) {
205     THROWC("Test exception!", e);
206     }
207     }
208    
209     int main(int argc, char *argv[]) {
210     Debugger::initStackTrace(argv[0]);
211    
212     try {
213     a("test");
214     } catch (const Exception &e) {
215     cerr << "Exception: " << e << endl;
216     }
217    
218     return 0;
219     }
220    
221     #endif // DEBUGGER_TEST