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