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