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[PETSC_MAX_PATH_LEN];
21: static PetscTruth Xterm = PETSC_TRUE;
23: #undef __FUNCT__
25: /*@C
26: PetscSetDebugger - Sets options associated with the debugger.
28: Not Collective
30: Input Parameters:
31: + debugger - name of debugger, which should be in your path,
32: usually "dbx", "gdb", or "xxgdb". Also, HP-UX
33: supports "xdb", and IBM rs6000 supports "xldb".
35: - xterm - flag to indicate debugger window, set to either 1 (to indicate
36: debugger should be started in a new xterm) or 0 (to start debugger
37: in initial window (the option 0 makes no sense when using more
38: than one processor.)
40: Level: developer
42: Fortran Note:
43: This routine is not supported in Fortran.
45: Concepts: debugger^setting
47: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
48: @*/
49: int PetscSetDebugger(const char debugger[],PetscTruth xterm)
50: {
54: if (debugger) {
55: PetscStrcpy(Debugger,debugger);
56: }
57: Xterm = xterm;
59: return(0);
60: }
62: #undef __FUNCT__
64: /*@
65: PetscSetDefaultDebugger - Causes PETSc to use its default
66: debugger.
68: Not collective
70: Level: advanced
72: .seealso: PetscSetDebugger(), PetscSetDebuggerFromString()
73: @*/
74: int PetscSetDefaultDebugger(void)
75: {
79: #if defined(PETSC_USE_DBX_DEBUGGER)
80: PetscSetDebugger("dbx",PETSC_TRUE);
81: #elif defined(PETSC_USE_XDB_DEBUGGER)
82: PetscSetDebugger("xdb",PETSC_TRUE);
83: #else /* Default is gdb */
84: PetscSetDebugger("gdb",PETSC_TRUE);
85: #endif
86: return(0);
87: }
89: #undef __FUNCT__
92: {
93: PetscTruth exists;
94: char *f;
95: int ierr;
98: PetscStrstr(string, defaultDbg, &f);
99: if (f) {
100: PetscTestFile(string, 'x', &exists);
101: if (exists) {
102: *debugger = string;
103: } else {
104: *debugger = defaultDbg;
105: }
106: }
107: return(0);
108: }
110: #undef __FUNCT__
112: /*@C
113: PetscSetDebuggerFromString - Set the complete path for the
114: debugger for PETSc to use.
116: Not collective
117:
118: Level: advanced
120: .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
121: @*/
122: int PetscSetDebuggerFromString(char *string)
123: {
124: char *debugger = PETSC_NULL;
125: PetscTruth xterm = PETSC_TRUE;
126: char *f;
127: int ierr;
130: PetscStrstr(string, "noxterm", &f);
131: if (f) xterm = PETSC_FALSE;
140: PetscSetDebugger(debugger, xterm);
141: return(0);
142: }
145: #undef __FUNCT__
147: /*@C
148: PetscAttachDebugger - Attaches the debugger to the running process.
150: Not Collective
152: Level: advanced
154: Concepts: debugger^starting from program
156: .seealso: PetscSetDebugger()
157: @*/
158: int PetscAttachDebugger(void)
159: {
160: int child=0,sleeptime=0,ierr=0;
161: char program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
165: PetscGetDisplay(display,128);
166: PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
167: if (ierr) {
168: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
169: PetscFunctionReturn(1);
170: }
172: #if defined(PETSC_CANNOT_START_DEBUGGER)
173: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debuggern");
174: (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debuggern");
175: (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)n");
176: MPI_Finalize();
177: exit(0);
178: #else
179: if (!program[0]) {
180: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
181: PetscFunctionReturn(1);
182: }
183: child = (int)fork();
184: if (child < 0) {
185: (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debuggern");
186: PetscFunctionReturn(1);
187: }
189: /*
190: Swap role the parent and child. This is (I think) so that control c typed
191: in the debugger goes to the correct process.
192: */
193: if (child) { child = 0; }
194: else { child = (int)getppid(); }
196: if (child) { /* I am the parent, will run the debugger */
197: char *args[9],pid[9];
198: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb,isworkshop;
200: PetscGetHostName(hostname,64);
201: /*
202: We need to send a continue signal to the "child" process on the
203: alpha, otherwise it just stays off forever
204: */
205: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
206: kill(child,SIGCONT);
207: #endif
208: sprintf(pid,"%d",child);
210: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
211: PetscStrcmp(Debugger,"ups",&isups);
212: PetscStrcmp(Debugger,"xldb",&isxldb);
213: PetscStrcmp(Debugger,"xdb",&isxdb);
214: PetscStrcmp(Debugger,"dbx",&isdbx);
215: PetscStrcmp(Debugger,"workshop",&isworkshop);
216: if (isxxgdb || isups) {
217: args[1] = program; args[2] = pid; args[3] = "-display";
218: args[0] = Debugger; args[4] = display; args[5] = 0;
219: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
220: if (execvp(args[0],args) < 0) {
221: perror("Unable to start debugger");
222: exit(0);
223: }
224: } else if (isxldb) {
225: args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display";
226: args[0] = Debugger; args[5] = display; args[6] = 0;
227: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
228: if (execvp(args[0],args) < 0) {
229: perror("Unable to start debugger");
230: exit(0);
231: }
232: } else if (isworkshop) {
233: args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
234: args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
235: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %sn",args[0],pid,hostname);
236: if (execvp(args[0],args) < 0) {
237: perror("Unable to start debugger");
238: exit(0);
239: }
240: } else if (!Xterm) {
241: args[1] = program; args[2] = pid; args[3] = 0;
242: args[0] = Debugger;
243: #if defined(PETSC_USE_P_FOR_DEBUGGER)
244: if (isdbx) {
245: args[1] = "-p";
246: args[2] = pid;
247: args[3] = program;
248: args[4] = 0;
249: }
250: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
251: if (isxdb) {
252: args[1] = "-l";
253: args[2] = "ALL";
254: args[3] = "-P";
255: args[4] = pid;
256: args[5] = program;
257: args[6] = 0;
258: }
259: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
260: if (isdbx) {
261: args[1] = "-a";
262: args[2] = pid;
263: args[3] = 0;
264: }
265: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
266: if (isdbx) {
267: args[1] = "-pid";
268: args[2] = pid;
269: args[3] = program;
270: args[4] = 0;
271: }
272: #endif
273: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %sn",Debugger,program,pid,hostname);
274: if (execvp(args[0],args) < 0) {
275: perror("Unable to start debugger");
276: exit(0);
277: }
278: } else {
279: if (!display[0]) {
280: args[0] = "xterm"; args[1] = "-e";
281: args[2] = Debugger; args[3] = program;
282: args[4] = pid; args[5] = 0;
283: #if defined(PETSC_USE_P_FOR_DEBUGGER)
284: if (isdbx) {
285: args[3] = "-p";
286: args[4] = pid;
287: args[5] = program;
288: args[6] = 0;
289: }
290: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
291: if (isxdb) {
292: args[5] = program;
293: args[3] = "-P";
294: args[4] = pid;
295: args[6] = 0;
296: }
297: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
298: if (isdbx) {
299: args[3] = "-a";
300: args[4] = pid;
301: args[5] = 0;
302: }
303: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
304: if (isdbx) {
305: args[3] = "-pid";
306: args[4] = pid;
307: args[5] = program;
308: args[6] = 0;
309: }
310: #endif
311: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %sn",Debugger,program,pid,hostname);
312: } else {
313: args[0] = "xterm"; args[1] = "-display";
314: args[2] = display; args[3] = "-e";
315: args[4] = Debugger; args[5] = program;
316: args[6] = pid; args[7] = 0;
317: #if defined(PETSC_USE_P_FOR_DEBUGGER)
318: if (isdbx) {
319: args[5] = "-p";
320: args[6] = pid;
321: args[7] = program;
322: args[8] = 0;
323: }
324: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
325: if (isxdb) {
326: args[7] = program;
327: args[5] = "-P";
328: args[6] = pid;
329: args[8] = 0;
330: }
331: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
332: if (isdbx) {
333: args[5] = "-a";
334: args[6] = pid;
335: args[7] = 0;
336: }
337: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
338: if (isdbx) {
339: args[5] = "-pid";
340: args[6] = pid;
341: args[7] = program;
342: args[8] = 0;
343: }
344: #endif
345: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %sn",Debugger,program,pid,display,hostname);
346: }
348: if (execvp("xterm",args) < 0) {
349: perror("Unable to start debugger");
350: exit(0);
351: }
352: }
353: } else { /* I am the child, continue with user code */
354: sleeptime = 10; /* default to sleep waiting for debugger */
355: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
356: if (sleeptime < 0) sleeptime = -sleeptime;
357: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
358: /*
359: HP cannot attach process to sleeping debugger, hence count instead
360: */
361: {
362: PetscReal x = 1.0;
363: int i=10000000;
364: while (i--) x++ ; /* cannot attach to sleeper */
365: }
366: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
367: /*
368: IBM sleep may return at anytime, hence must see if there is more time to sleep
369: */
370: {
371: int left = sleeptime;
372: while (left > 0) {left = PetscSleep(left) - 1;}
373: }
374: #else
375: PetscSleep(sleeptime);
376: #endif
377: }
378: #endif
379: return(0);
380: }
382: #undef __FUNCT__
384: /*@C
385: PetscAttachDebuggerErrorHandler - Error handler that attaches
386: a debugger to a running process when an error is detected.
387: This routine is useful for examining variables, etc.
389: Not Collective
391: Input Parameters:
392: + line - the line number of the error (indicated by __LINE__)
393: . fun - function where error occured (indicated by __FUNCT__)
394: . file - the file in which the error was detected (indicated by __FILE__)
395: . dir - the directory of the file (indicated by __SDIR__)
396: . message - an error text string, usually just printed to the screen
397: . number - the generic error number
398: . p - the specific error number
399: - ctx - error handler context
401: Options Database Keys:
402: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
403: debugger attachment
405: Level: developer
407: Notes:
408: By default the GNU debugger, gdb, is used. Alternatives are dbx and
409: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
411: Most users need not directly employ this routine and the other error
412: handlers, but can instead use the simplified interface SETERR, which has
413: the calling sequence
414: $ SETERRQ(number,p,message)
416: Notes for experienced users:
417: Use PetscPushErrorHandler() to set the desired error handler. The
418: currently available PETSc error handlers are
419: $ PetscTraceBackErrorHandler()
420: $ PetscAttachDebuggerErrorHandler()
421: $ PetscAbortErrorHandler()
422: or you may write your own.
424: Concepts: debugger^error handler
425: Concepts: error handler^attach debugger
427: .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
428: PetscAbortErrorHandler()
429: @*/
430: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
431: {
432: int ierr,rank;
435: if (!fun) fun = "User provided function";
436: if (!dir) dir = " ";
437: if (!mess) mess = " ";
439: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
440: (*PetscErrorPrintf)("[%d]PETSC ERROR: %s() line %d in %s%s %sn",rank,fun,line,dir,file,mess);
442: PetscAttachDebugger();
443: if (ierr) { /* hopeless so get out */
444: MPI_Finalize();
445: exit(num);
446: }
447: return(0);
448: }
450: #undef __FUNCT__
452: /*@C
453: PetscStopForDebugger - Prints a message to the screen indicating how to
454: attach to the process with the debugger and then waits for the
455: debugger to attach.
457: Not Collective
459: Level: advanced
461: Concepts: debugger^waiting for attachment
463: .seealso: PetscSetDebugger(), PetscAttachDebugger()
464: @*/
465: int PetscStopForDebugger(void)
466: {
467: int sleeptime=0,ierr,ppid,rank;
468: char program[256],hostname[256];
469: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;
473: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
474: PetscGetHostName(hostname,256);
475: if (ierr) {
476: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing programn");
477: return(0);
478: }
480: PetscGetProgramName(program,256);
481: if (ierr) {
482: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
483: return(0);
484: }
486: #if defined(PETSC_CANNOT_START_DEBUGGER)
487: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing programn");
488: #else
489: if (!program[0]) {
490: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
491: return(0);
492: }
494: ppid = getpid();
496: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
497: PetscStrcmp(Debugger,"ups",&isups);
498: PetscStrcmp(Debugger,"xldb",&isxldb);
499: PetscStrcmp(Debugger,"xdb",&isxdb);
500: PetscStrcmp(Debugger,"dbx",&isdbx);
502: if (isxxgdb || isups) {
503: (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
504: }
505: #if defined(PETSC_USE_A_FOR_DEBUGGER)
506: else if (isxldb) {
507: (*PetscErrorPrintf)("{%d]%s>>%s -a %d %sn",rank,hostname,Debugger,ppid,program);
508: }
509: #endif
510: #if defined(PETSC_USE_P_FOR_DEBUGGER)
511: else if (isdbx) {
512: (*PetscErrorPrintf)("[%d]%s>>%s -p %d %sn",rank,hostname,Debugger,ppid,program);
513: }
514: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
515: else if (isxdb) {
516: (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %sn",rank,hostname,Debugger,ppid,program);
517: }
518: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
519: else if (isdbx) {
520: (*PetscErrorPrintf)("[%d]%s>>%s -a %dn",rank,hostname,Debugger,ppid);
521: }
522: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
523: else if (isdbx) {
524: (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %sn",rank,hostname,Debugger,ppid,program);
525: }
526: #else
527: else {
528: (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
529: }
530: #endif
531: #endif /* PETSC_CANNOT_START_DEBUGGER */
533: fflush(stdout);
535: sleeptime = 25; /* default to sleep waiting for debugger */
536: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
537: if (sleeptime < 0) sleeptime = -sleeptime;
538: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
539: /*
540: HP cannot attach process to sleeping debugger, hence count instead
541: */
542: {
543: PetscReal x = 1.0;
544: int i=10000000;
545: while (i--) x++ ; /* cannot attach to sleeper */
546: }
547: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
548: /*
549: IBM sleep may return at anytime, hence must see if there is more time to sleep
550: */
551: {
552: int left = sleeptime;
553: while (left > 0) {left = sleep(left) - 1;}
554: }
555: #else
556: PetscSleep(sleeptime);
557: #endif
558: return(0);
559: }