Actual source code: adebug.c
petsc-3.3-p7 2013-05-11
1: /*
2: Code to handle PETSc starting up in debuggers,etc.
3: */
5: #include <petscsys.h> /*I "petscsys.h" I*/
6: #include <signal.h>
7: #if defined(PETSC_HAVE_UNISTD_H)
8: #include <unistd.h>
9: #endif
10: #if defined(PETSC_HAVE_STDLIB_H)
11: #include <stdlib.h>
12: #endif
14: /*
15: These are the debugger and display used if the debugger is started up
16: */
17: static char Debugger[PETSC_MAX_PATH_LEN];
18: static char DebugTerminal[PETSC_MAX_PATH_LEN];
19: static PetscBool Xterm = PETSC_TRUE;
23: /*@C
24: PetscSetDebugTerminal - Sets the terminal to use (instead of xterm) for debugging.
26: Not Collective
28: Input Parameters:
29: + terminal - name of terminal and any flags required to execute a program.
30: For example "xterm -e", "urxvt -e".
32: Options Database Keys:
33: -debug_terminal terminal - use this terminal instead of xterm
35: Level: developer
37: Notes:
38: You can start the debugger for all processes in the same GNU screen session.
40: mpirun -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"
42: will open 4 windows in the session named "debug".
43:
44: Fortran Note:
45: This routine is not supported in Fortran.
47: Concepts: debugger^setting
49: .seealso: PetscSetDebugger()
50: @*/
51: PetscErrorCode PetscSetDebugTerminal(const char terminal[])
52: {
56: PetscStrcpy(DebugTerminal,terminal);
57: return(0);
58: }
62: /*@C
63: PetscSetDebugger - Sets options associated with the debugger.
65: Not Collective
67: Input Parameters:
68: + debugger - name of debugger, which should be in your path,
69: usually "dbx", "gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
70: supports "xdb", and IBM rs6000 supports "xldb".
72: - xterm - flag to indicate debugger window, set to either 1 (to indicate
73: debugger should be started in a new xterm) or 0 (to start debugger
74: in initial window (the option 0 makes no sense when using more
75: than one processor.)
77: Level: developer
79: Fortran Note:
80: This routine is not supported in Fortran.
82: Concepts: debugger^setting
84: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
85: @*/
86: PetscErrorCode PetscSetDebugger(const char debugger[],PetscBool xterm)
87: {
91: if (debugger) {
92: PetscStrcpy(Debugger,debugger);
93: }
94: Xterm = xterm;
95: return(0);
96: }
100: /*@
101: PetscSetDefaultDebugger - Causes PETSc to use its default debugger.
103: Not collective
105: Level: advanced
107: .seealso: PetscSetDebugger(), PetscSetDebuggerFromString()
108: @*/
109: PetscErrorCode PetscSetDefaultDebugger(void)
110: {
114: #if defined(PETSC_USE_DBX_DEBUGGER)
115: PetscSetDebugger("dbx",PETSC_TRUE);
116: #elif defined(PETSC_USE_XDB_DEBUGGER)
117: PetscSetDebugger("xdb",PETSC_TRUE);
118: #elif defined(PETSC_USE_IDB_DEBUGGER)
119: PetscSetDebugger("idb",PETSC_TRUE);
120: #else /* Default is gdb */
121: PetscSetDebugger("gdb",PETSC_TRUE);
122: #endif
123: PetscSetDebugTerminal("xterm -e");
124: return(0);
125: }
130: {
131: PetscBool exists;
132: char *f;
136: PetscStrstr(string, defaultDbg, &f);
137: if (f) {
138: PetscTestFile(string, 'x', &exists);
139: if (exists) {
140: *debugger = string;
141: } else {
142: *debugger = defaultDbg;
143: }
144: }
145: return(0);
146: }
150: /*@C
151: PetscSetDebuggerFromString - Set the complete path for the
152: debugger for PETSc to use.
154: Not collective
155:
156: Level: developer
158: .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
159: @*/
160: PetscErrorCode PetscSetDebuggerFromString(const char *string)
161: {
162: const char *debugger = PETSC_NULL;
163: PetscBool xterm = PETSC_TRUE;
164: char *f;
168: PetscStrstr(string, "noxterm", &f);
169: if (f) xterm = PETSC_FALSE;
170: PetscStrstr(string, "ddd", &f);
171: if (f) xterm = PETSC_FALSE;
185: PetscSetDebugger(debugger, xterm);
186: return(0);
187: }
192: /*@
193: PetscAttachDebugger - Attaches the debugger to the running process.
195: Not Collective
197: Level: advanced
199: Concepts: debugger^starting from program
201: Developer Notes: Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()?
203: .seealso: PetscSetDebugger()
204: @*/
205: PetscErrorCode PetscAttachDebugger(void)
206: {
207: #if !defined(PETSC_CANNOT_START_DEBUGGER)
208: int child=0;
209: PetscReal sleeptime=0;
211: char program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
212: #endif
216: #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
217: (*PetscErrorPrintf)("System cannot start debugger\n");
218: (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
219: (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
220: MPI_Abort(PETSC_COMM_WORLD,1);
221: #else
222: PetscGetDisplay(display,128);
223: PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
224: if (ierr) {
225: (*PetscErrorPrintf)("Cannot determine program name\n");
226: PetscFunctionReturn(1);
227: }
228: if (!program[0]) {
229: (*PetscErrorPrintf)("Cannot determine program name\n");
230: PetscFunctionReturn(1);
231: }
232: child = (int)fork();
233: if (child < 0) {
234: (*PetscErrorPrintf)("Error in fork() attaching debugger\n");
235: PetscFunctionReturn(1);
236: }
238: /*
239: Swap role the parent and child. This is (I think) so that control c typed
240: in the debugger goes to the correct process.
241: */
242: if (child) { child = 0; }
243: else { child = (int)getppid(); }
245: if (child) { /* I am the parent, will run the debugger */
246: const char *args[10];
247: char pid[10];
248: PetscInt j,jj;
249: PetscBool isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg;
251: PetscGetHostName(hostname,64);
252: /*
253: We need to send a continue signal to the "child" process on the
254: alpha, otherwise it just stays off forever
255: */
256: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
257: kill(child,SIGCONT);
258: #endif
259: sprintf(pid,"%d",child);
261: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
262: PetscStrcmp(Debugger,"ddd",&isddd);
263: PetscStrcmp(Debugger,"kdbg",&iskdbg);
264: PetscStrcmp(Debugger,"ups",&isups);
265: PetscStrcmp(Debugger,"xldb",&isxldb);
266: PetscStrcmp(Debugger,"xdb",&isxdb);
267: PetscStrcmp(Debugger,"dbx",&isdbx);
268: PetscStrcmp(Debugger,"idb",&isidb);
269: PetscStrcmp(Debugger,"workshop",&isworkshop);
271: if (isxxgdb || isups || isddd ) {
272: args[1] = program; args[2] = pid; args[3] = "-display";
273: args[0] = Debugger; args[4] = display; args[5] = 0;
274: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
275: if (execvp(args[0],(char**)args) < 0) {
276: perror("Unable to start debugger");
277: exit(0);
278: }
279: } else if (iskdbg) {
280: args[1] = "-p"; args[2] = pid; args[3] = program; args[4] = "-display";
281: args[0] = Debugger; args[5] = display; args[6] = 0;
282: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname);
283: if (execvp(args[0],(char**)args) < 0) {
284: perror("Unable to start debugger");
285: exit(0);
286: }
287: } else if (isxldb) {
288: args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display";
289: args[0] = Debugger; args[5] = display; args[6] = 0;
290: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
291: if (execvp(args[0],(char**)args) < 0) {
292: perror("Unable to start debugger");
293: exit(0);
294: }
295: } else if (isworkshop) {
296: args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
297: args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
298: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
299: if (execvp(args[0],(char**)args) < 0) {
300: perror("Unable to start debugger");
301: exit(0);
302: }
303: } else {
304: j = 0;
305: if (Xterm) {
306: PetscBool cmp;
307: char *tmp,*tmp1;
308: PetscStrncmp(DebugTerminal,"screen",6,&cmp);
309: if (cmp) display[0] = 0; /* when using screen, we never pass -display */
310: args[j++] = tmp = DebugTerminal;
311: if (display[0]) {
312: args[j++] = "-display"; args[j++] = display;
313: }
314: while (*tmp) {
315: PetscStrchr(tmp,' ',&tmp1);
316: if (!tmp1) break;
317: *tmp1 = 0;
318: tmp = tmp1+1;
319: args[j++] = tmp;
320: }
321: }
322: args[j++] = Debugger;
323: jj = j;
324: args[j++] = program; args[j++] = pid; args[j++] = 0;
326: if (isidb) {
327: j = jj;
328: args[j++] = "-pid";
329: args[j++] = pid;
330: args[j++] = "-gdb";
331: args[j++] = program;
332: args[j++] = 0;
333: }
334: #if defined(PETSC_USE_P_FOR_DEBUGGER)
335: if (isdbx) {
336: j = jj;
337: args[j++] = "-p";
338: args[j++] = pid;
339: args[j++] = program;
340: args[j++] = 0;
341: }
342: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
343: if (isxdb) {
344: j = jj;
345: args[j++] = "-l";
346: args[j++] = "ALL";
347: args[j++] = "-P";
348: args[j++] = pid;
349: args[j++] = program;
350: args[j++] = 0;
351: }
352: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
353: if (isdbx) {
354: j = jj;
355: args[j++] = "-a";
356: args[j++] = pid;
357: args[j++] = 0;
358: }
359: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
360: if (isdbx) {
361: j = jj;
362: args[j++] = "-pid";
363: args[j++] = pid;
364: args[j++] = program;
365: args[j++] = 0;
366: }
367: #endif
368: if (Xterm) {
369: if (display[0]) {
370: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname);
371: } else {
372: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname);
373: }
374: if (execvp(args[0],(char**)args) < 0) {
375: perror("Unable to start debugger in xterm");
376: exit(0);
377: }
378: } else {
379: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname);
380: if (execvp(args[0],(char**)args) < 0) {
381: perror("Unable to start debugger");
382: exit(0);
383: }
384: }
385: }
386: } else { /* I am the child, continue with user code */
387: sleeptime = 10; /* default to sleep waiting for debugger */
388: PetscOptionsGetReal(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
389: if (sleeptime < 0) sleeptime = -sleeptime;
390: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
391: /*
392: HP cannot attach process to sleeping debugger, hence count instead
393: */
394: {
395: PetscReal x = 1.0;
396: int i=10000000;
397: while (i--) x++ ; /* cannot attach to sleeper */
398: }
399: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
400: /*
401: IBM sleep may return at anytime, hence must see if there is more time to sleep
402: */
403: {
404: int left = sleeptime;
405: while (left > 0) {left = PetscSleep(left) - 1;}
406: }
407: #else
408: PetscSleep(sleeptime);
409: #endif
410: }
411: #endif
412: return(0);
413: }
417: /*@C
418: PetscAttachDebuggerErrorHandler - Error handler that attaches
419: a debugger to a running process when an error is detected.
420: This routine is useful for examining variables, etc.
422: Not Collective
424: Input Parameters:
425: + comm - communicator over which error occurred
426: . line - the line number of the error (indicated by __LINE__)
427: . fun - function where error occured (indicated by __FUNCT__)
428: . file - the file in which the error was detected (indicated by __FILE__)
429: . dir - the directory of the file (indicated by __SDIR__)
430: . message - an error text string, usually just printed to the screen
431: . number - the generic error number
432: . p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
433: - ctx - error handler context
435: Options Database Keys:
436: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
437: debugger attachment
439: Level: developer
441: Notes:
442: By default the GNU debugger, gdb, is used. Alternatives are dbx and
443: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
445: Most users need not directly employ this routine and the other error
446: handlers, but can instead use the simplified interface SETERR, which has
447: the calling sequence
448: $ SETERRQ(PETSC_COMM_SELF,number,p,message)
450: Notes for experienced users:
451: Use PetscPushErrorHandler() to set the desired error handler. The
452: currently available PETSc error handlers are
453: $ PetscTraceBackErrorHandler()
454: $ PetscAttachDebuggerErrorHandler()
455: $ PetscAbortErrorHandler()
456: or you may write your own.
458: Concepts: debugger^error handler
459: Concepts: error handler^attach debugger
461: .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
462: PetscAbortErrorHandler()
463: @*/
464: PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char* fun,const char *file,const char* dir,PetscErrorCode num,PetscErrorType p,const char* mess,void *ctx)
465: {
469: if (!fun) fun = "User provided function";
470: if (!dir) dir = " ";
471: if (!mess) mess = " ";
473: (*PetscErrorPrintf)("%s() line %d in %s%s %s\n",fun,line,dir,file,mess);
475: PetscAttachDebugger();
476: if (ierr) { /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
477: abort();
478: }
479: return(0);
480: }
484: /*@C
485: PetscStopForDebugger - Prints a message to the screen indicating how to
486: attach to the process with the debugger and then waits for the
487: debugger to attach.
489: Not Collective
491: Level: advanced
493: Developer Notes: Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()?
495: Concepts: debugger^waiting for attachment
497: .seealso: PetscSetDebugger(), PetscAttachDebugger()
498: @*/
499: PetscErrorCode 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: PetscBool isdbx,isxldb,isxxgdb,isddd,iskdbg,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: if (ierr) rank = 0; /* ignore error since this may be already in error handler */
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,"kdbg",&iskdbg);
537: PetscStrcmp(Debugger,"ups",&isups);
538: PetscStrcmp(Debugger,"xldb",&isxldb);
539: PetscStrcmp(Debugger,"xdb",&isxdb);
540: PetscStrcmp(Debugger,"dbx",&isdbx);
542: if (isxxgdb || isups || isddd || iskdbg ) {
543: (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
544: }
545: #if defined(PETSC_USE_A_FOR_DEBUGGER)
546: else if (isxldb) {
547: (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program);
548: }
549: #endif
550: #if defined(PETSC_USE_P_FOR_DEBUGGER)
551: else if (isdbx) {
552: (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program);
553: }
554: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
555: else if (isxdb) {
556: (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program);
557: }
558: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
559: else if (isdbx) {
560: (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid);
561: }
562: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
563: else if (isdbx) {
564: (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program);
565: }
566: #else
567: else {
568: (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
569: }
570: #endif
571: #endif /* PETSC_CANNOT_START_DEBUGGER */
573: fflush(stdout); /* ignore error because may already be in error handler */
575: sleeptime = 25; /* default to sleep waiting for debugger */
576: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL); /* ignore error because may already be in error handler */
577: if (sleeptime < 0) sleeptime = -sleeptime;
578: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
579: /*
580: HP cannot attach process to sleeping debugger, hence count instead
581: */
582: {
583: PetscReal x = 1.0;
584: int i=10000000;
585: while (i--) x++ ; /* cannot attach to sleeper */
586: }
587: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
588: /*
589: IBM sleep may return at anytime, hence must see if there is more time to sleep
590: */
591: {
592: int left = sleeptime;
593: while (left > 0) {left = sleep(left) - 1;}
594: }
595: #else
596: PetscSleep(sleeptime);
597: #endif
598: return(0);
599: }