Actual source code: adebug.c
1: /*$Id: adebug.c,v 1.113 2001/03/23 23:20:26 balay Exp $*/
2: /*
3: Code to handle PETSc starting up in debuggers,etc.
4: */
6: #include petsc.h
7: #include <signal.h>
8: #include petscsys.h
9: #if defined(PETSC_HAVE_UNISTD_H)
10: #include <unistd.h>
11: #endif
12: #if defined(PETSC_HAVE_STDLIB_H)
13: #include <stdlib.h>
14: #endif
15: #include "petscfix.h"
17: /*
18: These are the debugger and display used if the debugger is started up
19: */
20: static char Debugger[256];
21: static PetscTruth Xterm = PETSC_TRUE;
23: /*@C
24: PetscSetDebugger - Sets options associated with the debugger.
26: Not Collective
28: Input Parameters:
29: + debugger - name of debugger, which should be in your path,
30: usually "dbx", "gdb", or "xxgdb". Also, HP-UX
31: supports "xdb", and IBM rs6000 supports "xldb".
33: - xterm - flag to indicate debugger window, set to either 1 (to indicate
34: debugger should be started in a new xterm) or 0 (to start debugger
35: in initial window (the option 0 makes no sense when using more
36: than one processor.)
38: Level: developer
40: Fortran Note:
41: This routine is not supported in Fortran.
43: Concepts: debugger^setting
45: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
46: @*/
47: int PetscSetDebugger(const char debugger[],PetscTruth xterm)
48: {
52: if (debugger) {
53: PetscStrcpy(Debugger,debugger);
54: }
55: Xterm = xterm;
57: return(0);
58: }
60: int PetscSetDefaultDebugger(void)
61: {
65: #if defined(PETSC_USE_DBX_DEBUGGER)
66: PetscSetDebugger("dbx",PETSC_TRUE);
67: #elif defined(PETSC_USE_XDB_DEBUGGER)
68: PetscSetDebugger("xdb",PETSC_TRUE);
69: #else /* Default is gdb */
70: PetscSetDebugger("gdb",PETSC_TRUE);
71: #endif
72: return(0);
73: }
75: static int CheckForDefaultDebugger(char *defaultDbg, char *string, char **debugger)
76: {
77: PetscTruth exists;
78: char *f;
79: int ierr;
82: if (*debugger != PETSC_NULL) {
83: return(0);
84: }
85: PetscStrstr(string, defaultDbg, &f);
86: if (f) {
87: PetscTestFile(string, 'x', &exists);
88: if (exists) {
89: *debugger = string;
90: } else {
91: *debugger = defaultDbg;
92: }
93: }
94: return(0);
95: }
97: int PetscSetDebuggerFromString(char *string)
98: {
99: char *debugger = PETSC_NULL;
100: PetscTruth xterm = PETSC_TRUE;
101: char *f;
102: int ierr;
105: PetscStrstr(string, "noxterm", &f);
106: if (f) xterm = PETSC_FALSE;
107: CheckForDefaultDebugger("xdb", string, &debugger);
108: CheckForDefaultDebugger("dbx", string, &debugger);
109: CheckForDefaultDebugger("xldb", string, &debugger);
110: CheckForDefaultDebugger("gdb", string, &debugger);
111: CheckForDefaultDebugger("xxgdb", string, &debugger);
112: CheckForDefaultDebugger("ups", string, &debugger);
113: CheckForDefaultDebugger("workshop", string, &debugger);
114: CheckForDefaultDebugger("pgdbg", string, &debugger);
115: PetscSetDebugger(debugger, xterm);
116: return(0);
117: }
120: /*@C
121: PetscAttachDebugger - Attaches the debugger to the running process.
123: Not Collective
125: Level: advanced
127: Concepts: debugger^starting from program
129: .seealso: PetscSetDebugger()
130: @*/
131: int PetscAttachDebugger(void)
132: {
133: int child=0,sleeptime=0,ierr=0;
134: char program[256],display[256],hostname[64];
138: PetscGetDisplay(display,128);
139: PetscGetProgramName(program,256);
140: if (ierr) {
141: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
142: PetscFunctionReturn(1);
143: }
145: #if defined(PETSC_CANNOT_START_DEBUGGER)
146: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debuggern");
147: (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debuggern");
148: (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)n");
149: MPI_Finalize();
150: exit(0);
151: #else
152: if (!program[0]) {
153: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
154: PetscFunctionReturn(1);
155: }
156: child = (int)fork();
157: if (child < 0) {
158: (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debuggern");
159: PetscFunctionReturn(1);
160: }
162: /*
163: Swap role the parent and child. This is (I think) so that control c typed
164: in the debugger goes to the correct process.
165: */
166: if (child) { child = 0; }
167: else { child = (int)getppid(); }
169: if (child) { /* I am the parent, will run the debugger */
170: char *args[9],pid[9];
171: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb,isworkshop;
173: PetscGetHostName(hostname,64);
174: /*
175: We need to send a continue signal to the "child" process on the
176: alpha, otherwise it just stays off forever
177: */
178: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
179: kill(child,SIGCONT);
180: #endif
181: sprintf(pid,"%d",child);
183: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
184: PetscStrcmp(Debugger,"ups",&isups);
185: PetscStrcmp(Debugger,"xldb",&isxldb);
186: PetscStrcmp(Debugger,"xdb",&isxdb);
187: PetscStrcmp(Debugger,"dbx",&isdbx);
188: PetscStrcmp(Debugger,"workshop",&isworkshop);
189: if (isxxgdb || isups) {
190: args[1] = program; args[2] = pid; args[3] = "-display";
191: args[0] = Debugger; args[4] = display; args[5] = 0;
192: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
193: if (execvp(args[0],args) < 0) {
194: perror("Unable to start debugger");
195: exit(0);
196: }
197: } else if (isxldb) {
198: args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display";
199: args[0] = Debugger; args[5] = display; args[6] = 0;
200: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
201: if (execvp(args[0],args) < 0) {
202: perror("Unable to start debugger");
203: exit(0);
204: }
205: } else if (isworkshop) {
206: args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
207: args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
208: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %sn",args[0],pid,hostname);
209: if (execvp(args[0],args) < 0) {
210: perror("Unable to start debugger");
211: exit(0);
212: }
213: } else if (!Xterm) {
214: args[1] = program; args[2] = pid; args[3] = 0;
215: args[0] = Debugger;
216: #if defined(PETSC_USE_P_FOR_DEBUGGER)
217: if (isdbx) {
218: args[1] = "-p";
219: args[2] = pid;
220: args[3] = program;
221: args[4] = 0;
222: }
223: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
224: if (isxdb) {
225: args[1] = "-l";
226: args[2] = "ALL";
227: args[3] = "-P";
228: args[4] = pid;
229: args[5] = program;
230: args[6] = 0;
231: }
232: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
233: if (isdbx) {
234: args[1] = "-a";
235: args[2] = pid;
236: args[3] = 0;
237: }
238: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
239: if (isdbx) {
240: args[1] = "-pid";
241: args[2] = pid;
242: args[3] = program;
243: args[4] = 0;
244: }
245: #endif
246: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %sn",Debugger,program,pid,hostname);
247: if (execvp(args[0],args) < 0) {
248: perror("Unable to start debugger");
249: exit(0);
250: }
251: } else {
252: if (!display[0]) {
253: args[0] = "xterm"; args[1] = "-e";
254: args[2] = Debugger; args[3] = program;
255: args[4] = pid; args[5] = 0;
256: #if defined(PETSC_USE_P_FOR_DEBUGGER)
257: if (isdbx) {
258: args[3] = "-p";
259: args[4] = pid;
260: args[5] = program;
261: args[6] = 0;
262: }
263: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
264: if (isxdb) {
265: args[5] = program;
266: args[3] = "-P";
267: args[4] = pid;
268: args[6] = 0;
269: }
270: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
271: if (isdbx) {
272: args[3] = "-a";
273: args[4] = pid;
274: args[5] = 0;
275: }
276: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
277: if (isdbx) {
278: args[3] = "-pid";
279: args[4] = pid;
280: args[5] = program;
281: args[6] = 0;
282: }
283: #endif
284: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %sn",Debugger,program,pid,hostname);
285: } else {
286: args[0] = "xterm"; args[1] = "-display";
287: args[2] = display; args[3] = "-e";
288: args[4] = Debugger; args[5] = program;
289: args[6] = pid; args[7] = 0;
290: #if defined(PETSC_USE_P_FOR_DEBUGGER)
291: if (isdbx) {
292: args[5] = "-p";
293: args[6] = pid;
294: args[7] = program;
295: args[8] = 0;
296: }
297: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
298: if (isxdb) {
299: args[7] = program;
300: args[5] = "-P";
301: args[6] = pid;
302: args[8] = 0;
303: }
304: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
305: if (isdbx) {
306: args[5] = "-a";
307: args[6] = pid;
308: args[7] = 0;
309: }
310: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
311: if (isdbx) {
312: args[5] = "-pid";
313: args[6] = pid;
314: args[7] = program;
315: args[8] = 0;
316: }
317: #endif
318: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %sn",Debugger,program,pid,display,hostname);
319: }
321: if (execvp("xterm",args) < 0) {
322: perror("Unable to start debugger");
323: exit(0);
324: }
325: }
326: } else { /* I am the child, continue with user code */
327: sleeptime = 10; /* default to sleep waiting for debugger */
328: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
329: if (sleeptime < 0) sleeptime = -sleeptime;
330: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
331: /*
332: HP cannot attach process to sleeping debugger, hence count instead
333: */
334: {
335: PetscReal x = 1.0;
336: int i=10000000;
337: while (i--) x++ ; /* cannot attach to sleeper */
338: }
339: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
340: /*
341: IBM sleep may return at anytime, hence must see if there is more time to sleep
342: */
343: {
344: int left = sleeptime;
345: while (left > 0) {left = PetscSleep(left) - 1;}
346: }
347: #else
348: PetscSleep(sleeptime);
349: #endif
350: }
351: #endif
352: return(0);
353: }
355: /*@C
356: PetscAttachDebuggerErrorHandler - Error handler that attaches
357: a debugger to a running process when an error is detected.
358: This routine is useful for examining variables, etc.
360: Not Collective
362: Input Parameters:
363: + line - the line number of the error (indicated by __LINE__)
364: . file - the file in which the error was detected (indicated by __FILE__)
365: . dir - the directory of the file (indicated by __SDIR__)
366: . message - an error text string, usually just printed to the screen
367: . number - the generic error number
368: . p - the specific error number
369: - ctx - error handler context
371: Options Database Keys:
372: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
373: debugger attachment
375: Level: developer
377: Notes:
378: By default the GNU debugger, gdb, is used. Alternatives are dbx and
379: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
381: Most users need not directly employ this routine and the other error
382: handlers, but can instead use the simplified interface SETERR, which has
383: the calling sequence
384: $ SETERRQ(number,p,message)
386: Notes for experienced users:
387: Use PetscPushErrorHandler() to set the desired error handler. The
388: currently available PETSc error handlers are
389: $ PetscTraceBackErrorHandler()
390: $ PetscAttachDebuggerErrorHandler()
391: $ PetscAbortErrorHandler()
392: or you may write your own.
394: Concepts: debugger^error handler
395: Concepts: error handler^attach debugger
397: .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
398: PetscAbortErrorHandler()
399: @*/
400: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
401: {
402: int ierr,rank;
405: if (!fun) fun = "unknownfunction";
406: if (!dir) dir = " ";
407: if (!mess) mess = " ";
409: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
410: (*PetscErrorPrintf)("[%d]PETSC ERROR: %s() line %d in %s%s %sn",rank,fun,line,dir,file,mess);
412: PetscAttachDebugger();
413: if (ierr) { /* hopeless so get out */
414: MPI_Finalize();
415: exit(num);
416: }
417: return(0);
418: }
420: /*@C
421: PetscStopForDebugger - Prints a message to the screen indicating how to
422: attach to the process with the debugger and then waits for the
423: debugger to attach.
425: Not Collective
427: Level: advanced
429: Concepts: debugger^waiting for attachment
431: .seealso: PetscSetDebugger(), PetscAttachDebugger()
432: @*/
433: int PetscStopForDebugger(void)
434: {
435: int sleeptime=0,ierr,ppid,rank;
436: char program[256],hostname[256];
437: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;
441: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
442: PetscGetHostName(hostname,256);
443: if (ierr) {
444: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing programn");
445: return(0);
446: }
448: PetscGetProgramName(program,256);
449: if (ierr) {
450: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
451: return(0);
452: }
454: #if defined(PETSC_CANNOT_START_DEBUGGER)
455: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing programn");
456: #else
457: if (!program[0]) {
458: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
459: return(0);
460: }
462: ppid = getpid();
464: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
465: PetscStrcmp(Debugger,"ups",&isups);
466: PetscStrcmp(Debugger,"xldb",&isxldb);
467: PetscStrcmp(Debugger,"xdb",&isxdb);
468: PetscStrcmp(Debugger,"dbx",&isdbx);
470: if (isxxgdb || isups) {
471: (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
472: }
473: #if defined(PETSC_USE_A_FOR_DEBUGGER)
474: else if (isxldb) {
475: (*PetscErrorPrintf)("{%d]%s>>%s -a %d %sn",rank,hostname,Debugger,ppid,program);
476: }
477: #endif
478: #if defined(PETSC_USE_P_FOR_DEBUGGER)
479: else if (isdbx) {
480: (*PetscErrorPrintf)("[%d]%s>>%s -p %d %sn",rank,hostname,Debugger,ppid,program);
481: }
482: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
483: else if (isxdb) {
484: (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %sn",rank,hostname,Debugger,ppid,program);
485: }
486: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
487: else if (isdbx) {
488: (*PetscErrorPrintf)("[%d]%s>>%s -a %dn",rank,hostname,Debugger,ppid);
489: }
490: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
491: else if (isdbx) {
492: (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %sn",rank,hostname,Debugger,ppid,program);
493: }
494: #else
495: else {
496: (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
497: }
498: #endif
499: #endif /* PETSC_CANNOT_START_DEBUGGER */
501: fflush(stdout);
503: sleeptime = 25; /* default to sleep waiting for debugger */
504: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
505: if (sleeptime < 0) sleeptime = -sleeptime;
506: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
507: /*
508: HP cannot attach process to sleeping debugger, hence count instead
509: */
510: {
511: PetscReal x = 1.0;
512: int i=10000000;
513: while (i--) x++ ; /* cannot attach to sleeper */
514: }
515: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
516: /*
517: IBM sleep may return at anytime, hence must see if there is more time to sleep
518: */
519: {
520: int left = sleeptime;
521: while (left > 0) {left = sleep(left) - 1;}
522: }
523: #else
524: PetscSleep(sleeptime);
525: #endif
526: return(0);
527: }