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;
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", "idb" 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: }
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: #elif defined(PETSC_USE_IDB_DEBUGGER)
84: PetscSetDebugger("idb",PETSC_TRUE);
85: #else /* Default is gdb */
86: PetscSetDebugger("gdb",PETSC_TRUE);
87: #endif
88: return(0);
89: }
94: {
95: PetscTruth exists;
96: char *f;
97: int ierr;
100: PetscStrstr(string, defaultDbg, &f);
101: if (f) {
102: PetscTestFile(string, 'x', &exists);
103: if (exists) {
104: *debugger = string;
105: } else {
106: *debugger = defaultDbg;
107: }
108: }
109: return(0);
110: }
114: /*@C
115: PetscSetDebuggerFromString - Set the complete path for the
116: debugger for PETSc to use.
118: Not collective
119:
120: Level: advanced
122: .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
123: @*/
124: int PetscSetDebuggerFromString(char *string)
125: {
126: char *debugger = PETSC_NULL;
127: PetscTruth xterm = PETSC_TRUE;
128: char *f;
129: int ierr;
132: PetscStrstr(string, "noxterm", &f);
133: if (f) xterm = PETSC_FALSE;
143: PetscSetDebugger(debugger, xterm);
144: return(0);
145: }
150: /*@C
151: PetscAttachDebugger - Attaches the debugger to the running process.
153: Not Collective
155: Level: advanced
157: Concepts: debugger^starting from program
159: .seealso: PetscSetDebugger()
160: @*/
161: int PetscAttachDebugger(void)
162: {
163: #if !defined(PETSC_CANNOT_START_DEBUGGER)
164: int child=0,sleeptime=0,ierr=0;
165: char program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
166: #endif
170: #if defined(PETSC_CANNOT_START_DEBUGGER )
171: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger\n");
172: (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debugger\n");
173: (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)\n");
174: MPI_Finalize();
175: exit(0);
176: #else
177: PetscGetDisplay(display,128);
178: PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
179: if (ierr) {
180: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name\n");
181: PetscFunctionReturn(1);
182: }
183: if (!program[0]) {
184: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name\n");
185: PetscFunctionReturn(1);
186: }
187: child = (int)fork();
188: if (child < 0) {
189: (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debugger\n");
190: PetscFunctionReturn(1);
191: }
193: /*
194: Swap role the parent and child. This is (I think) so that control c typed
195: in the debugger goes to the correct process.
196: */
197: if (child) { child = 0; }
198: else { child = (int)getppid(); }
200: if (child) { /* I am the parent, will run the debugger */
201: char *args[10],pid[10];
202: PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop;
204: PetscGetHostName(hostname,64);
205: /*
206: We need to send a continue signal to the "child" process on the
207: alpha, otherwise it just stays off forever
208: */
209: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
210: kill(child,SIGCONT);
211: #endif
212: sprintf(pid,"%d",child);
214: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
215: PetscStrcmp(Debugger,"ups",&isups);
216: PetscStrcmp(Debugger,"xldb",&isxldb);
217: PetscStrcmp(Debugger,"xdb",&isxdb);
218: PetscStrcmp(Debugger,"dbx",&isdbx);
219: PetscStrcmp(Debugger,"idb",&isidb);
220: PetscStrcmp(Debugger,"workshop",&isworkshop);
221: if (isxxgdb || isups) {
222: args[1] = program; args[2] = pid; args[3] = "-display";
223: args[0] = Debugger; args[4] = display; args[5] = 0;
224: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
225: if (execvp(args[0],args) < 0) {
226: perror("Unable to start debugger");
227: exit(0);
228: }
229: } else if (isxldb) {
230: args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display";
231: args[0] = Debugger; args[5] = display; args[6] = 0;
232: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
233: if (execvp(args[0],args) < 0) {
234: perror("Unable to start debugger");
235: exit(0);
236: }
237: } else if (isworkshop) {
238: args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
239: args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
240: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
241: if (execvp(args[0],args) < 0) {
242: perror("Unable to start debugger");
243: exit(0);
244: }
245: } else if (!Xterm) {
246: args[1] = program; args[2] = pid; args[3] = 0;
247: args[0] = Debugger;
248: if (isidb) {
249: args[1] = "-pid";
250: args[2] = pid;
251: args[3] = "-gdb";
252: args[4] = program;
253: args[5] = 0;
254: }
255: #if defined(PETSC_USE_P_FOR_DEBUGGER)
256: if (isdbx) {
257: args[1] = "-p";
258: args[2] = pid;
259: args[3] = program;
260: args[4] = 0;
261: }
262: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
263: if (isxdb) {
264: args[1] = "-l";
265: args[2] = "ALL";
266: args[3] = "-P";
267: args[4] = pid;
268: args[5] = program;
269: args[6] = 0;
270: }
271: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
272: if (isdbx) {
273: args[1] = "-a";
274: args[2] = pid;
275: args[3] = 0;
276: }
277: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
278: if (isdbx) {
279: args[1] = "-pid";
280: args[2] = pid;
281: args[3] = program;
282: args[4] = 0;
283: }
284: #endif
285: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname);
286: if (execvp(args[0],args) < 0) {
287: perror("Unable to start debugger");
288: exit(0);
289: }
290: } else {
291: if (!display[0]) {
292: args[0] = "xterm"; args[1] = "-e";
293: args[2] = Debugger; args[3] = program;
294: args[4] = pid; args[5] = 0;
295: if (isidb) {
296: args[3] = "-gdb";
297: args[4] = pid;
298: args[5] = "-gdb";
299: args[6] = program;
300: args[7] = 0;
301: }
302: #if defined(PETSC_USE_P_FOR_DEBUGGER)
303: if (isdbx) {
304: args[3] = "-p";
305: args[4] = pid;
306: args[5] = program;
307: args[6] = 0;
308: }
309: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
310: if (isxdb) {
311: args[5] = program;
312: args[3] = "-P";
313: args[4] = pid;
314: args[6] = 0;
315: }
316: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
317: if (isdbx) {
318: args[3] = "-a";
319: args[4] = pid;
320: args[5] = 0;
321: }
322: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
323: if (isdbx) {
324: args[3] = "-pid";
325: args[4] = pid;
326: args[5] = program;
327: args[6] = 0;
328: }
329: #endif
330: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname);
331: } else {
332: args[0] = "xterm"; args[1] = "-display";
333: args[2] = display; args[3] = "-e";
334: args[4] = Debugger; args[5] = program;
335: args[6] = pid; args[7] = 0;
336: if (isidb) {
337: args[5] = "-pid";
338: args[6] = pid;
339: args[7] = "-gdb";
340: args[8] = program;
341: args[9] = 0;
342: }
343: #if defined(PETSC_USE_P_FOR_DEBUGGER)
344: if (isdbx) {
345: args[5] = "-p";
346: args[6] = pid;
347: args[7] = program;
348: args[8] = 0;
349: }
350: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
351: if (isxdb) {
352: args[7] = program;
353: args[5] = "-P";
354: args[6] = pid;
355: args[8] = 0;
356: }
357: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
358: if (isdbx) {
359: args[5] = "-a";
360: args[6] = pid;
361: args[7] = 0;
362: }
363: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
364: if (isdbx) {
365: args[5] = "-pid";
366: args[6] = pid;
367: args[7] = program;
368: args[8] = 0;
369: }
370: #endif
371: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname);
372: }
374: if (execvp("xterm",args) < 0) {
375: perror("Unable to start debugger");
376: exit(0);
377: }
378: }
379: } else { /* I am the child, continue with user code */
380: sleeptime = 10; /* default to sleep waiting for debugger */
381: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
382: if (sleeptime < 0) sleeptime = -sleeptime;
383: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
384: /*
385: HP cannot attach process to sleeping debugger, hence count instead
386: */
387: {
388: PetscReal x = 1.0;
389: int i=10000000;
390: while (i--) x++ ; /* cannot attach to sleeper */
391: }
392: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
393: /*
394: IBM sleep may return at anytime, hence must see if there is more time to sleep
395: */
396: {
397: int left = sleeptime;
398: while (left > 0) {left = PetscSleep(left) - 1;}
399: }
400: #else
401: PetscSleep(sleeptime);
402: #endif
403: }
404: #endif
405: return(0);
406: }
410: /*@C
411: PetscAttachDebuggerErrorHandler - Error handler that attaches
412: a debugger to a running process when an error is detected.
413: This routine is useful for examining variables, etc.
415: Not Collective
417: Input Parameters:
418: + line - the line number of the error (indicated by __LINE__)
419: . fun - function where error occured (indicated by __FUNCT__)
420: . file - the file in which the error was detected (indicated by __FILE__)
421: . dir - the directory of the file (indicated by __SDIR__)
422: . message - an error text string, usually just printed to the screen
423: . number - the generic error number
424: . p - the specific error number
425: - ctx - error handler context
427: Options Database Keys:
428: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
429: debugger attachment
431: Level: developer
433: Notes:
434: By default the GNU debugger, gdb, is used. Alternatives are dbx and
435: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
437: Most users need not directly employ this routine and the other error
438: handlers, but can instead use the simplified interface SETERR, which has
439: the calling sequence
440: $ SETERRQ(number,p,message)
442: Notes for experienced users:
443: Use PetscPushErrorHandler() to set the desired error handler. The
444: currently available PETSc error handlers are
445: $ PetscTraceBackErrorHandler()
446: $ PetscAttachDebuggerErrorHandler()
447: $ PetscAbortErrorHandler()
448: or you may write your own.
450: Concepts: debugger^error handler
451: Concepts: error handler^attach debugger
453: .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
454: PetscAbortErrorHandler()
455: @*/
456: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
457: {
458: int ierr,rank;
461: if (!fun) fun = "User provided function";
462: if (!dir) dir = " ";
463: if (!mess) mess = " ";
465: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
466: (*PetscErrorPrintf)("[%d]PETSC ERROR: %s() line %d in %s%s %s\n",rank,fun,line,dir,file,mess);
468: PetscAttachDebugger();
469: if (ierr) { /* hopeless so get out */
470: MPI_Finalize();
471: exit(num);
472: }
473: return(0);
474: }
478: /*@C
479: PetscStopForDebugger - Prints a message to the screen indicating how to
480: attach to the process with the debugger and then waits for the
481: debugger to attach.
483: Not Collective
485: Level: advanced
487: Concepts: debugger^waiting for attachment
489: .seealso: PetscSetDebugger(), PetscAttachDebugger()
490: @*/
491: int PetscStopForDebugger(void)
492: {
493: int ierr,sleeptime=0;
494: #if !defined(PETSC_CANNOT_START_DEBUGGER)
495: int ppid,rank;
496: char program[256],hostname[256];
497: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;
498: #endif
501: #if defined(PETSC_CANNOT_START_DEBUGGER)
502: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing program\n");
503: #else
504: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
505: PetscGetHostName(hostname,256);
506: if (ierr) {
507: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing program\n");
508: return(0);
509: }
511: PetscGetProgramName(program,256);
512: if (ierr) {
513: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing program\n");
514: return(0);
515: }
516: if (!program[0]) {
517: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing program\n");
518: return(0);
519: }
521: ppid = getpid();
523: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
524: PetscStrcmp(Debugger,"ups",&isups);
525: PetscStrcmp(Debugger,"xldb",&isxldb);
526: PetscStrcmp(Debugger,"xdb",&isxdb);
527: PetscStrcmp(Debugger,"dbx",&isdbx);
529: if (isxxgdb || isups) {
530: (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
531: }
532: #if defined(PETSC_USE_A_FOR_DEBUGGER)
533: else if (isxldb) {
534: (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program);
535: }
536: #endif
537: #if defined(PETSC_USE_P_FOR_DEBUGGER)
538: else if (isdbx) {
539: (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program);
540: }
541: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
542: else if (isxdb) {
543: (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program);
544: }
545: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
546: else if (isdbx) {
547: (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid);
548: }
549: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
550: else if (isdbx) {
551: (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program);
552: }
553: #else
554: else {
555: (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
556: }
557: #endif
558: #endif /* PETSC_CANNOT_START_DEBUGGER */
560: fflush(stdout);
562: sleeptime = 25; /* default to sleep waiting for debugger */
563: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
564: if (sleeptime < 0) sleeptime = -sleeptime;
565: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
566: /*
567: HP cannot attach process to sleeping debugger, hence count instead
568: */
569: {
570: PetscReal x = 1.0;
571: int i=10000000;
572: while (i--) x++ ; /* cannot attach to sleeper */
573: }
574: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
575: /*
576: IBM sleep may return at anytime, hence must see if there is more time to sleep
577: */
578: {
579: int left = sleeptime;
580: while (left > 0) {left = sleep(left) - 1;}
581: }
582: #else
583: PetscSleep(sleeptime);
584: #endif
585: return(0);
586: }