Actual source code: adebug.c
1: /*
2: Code to handle PETSc starting up in debuggers,etc.
3: */
5: #include petsc.h
6: #include <signal.h>
7: #include petscsys.h
8: #if defined(PETSC_HAVE_UNISTD_H)
9: #include <unistd.h>
10: #endif
11: #if defined(PETSC_HAVE_STDLIB_H)
12: #include <stdlib.h>
13: #endif
14: #include "petscfix.h"
16: /*
17: These are the debugger and display used if the debugger is started up
18: */
19: static char Debugger[PETSC_MAX_PATH_LEN];
20: static PetscTruth Xterm = PETSC_TRUE;
24: /*@C
25: PetscSetDebugger - Sets options associated with the debugger.
27: Not Collective
29: Input Parameters:
30: + debugger - name of debugger, which should be in your path,
31: usually "dbx", "gdb", "idb", "xxgdb" or "ddd". Also, HP-UX
32: supports "xdb", and IBM rs6000 supports "xldb".
34: - xterm - flag to indicate debugger window, set to either 1 (to indicate
35: debugger should be started in a new xterm) or 0 (to start debugger
36: in initial window (the option 0 makes no sense when using more
37: than one processor.)
39: Level: developer
41: Fortran Note:
42: This routine is not supported in Fortran.
44: Concepts: debugger^setting
46: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
47: @*/
48: PetscErrorCode PetscSetDebugger(const char debugger[],PetscTruth xterm)
49: {
53: if (debugger) {
54: PetscStrcpy(Debugger,debugger);
55: }
56: Xterm = xterm;
58: return(0);
59: }
63: /*@
64: PetscSetDefaultDebugger - Causes PETSc to use its default
65: debugger.
67: Not collective
69: Level: advanced
71: .seealso: PetscSetDebugger(), PetscSetDebuggerFromString()
72: @*/
73: PetscErrorCode PetscSetDefaultDebugger(void)
74: {
78: #if defined(PETSC_USE_DBX_DEBUGGER)
79: PetscSetDebugger("dbx",PETSC_TRUE);
80: #elif defined(PETSC_USE_XDB_DEBUGGER)
81: PetscSetDebugger("xdb",PETSC_TRUE);
82: #elif defined(PETSC_USE_IDB_DEBUGGER)
83: PetscSetDebugger("idb",PETSC_TRUE);
84: #else /* Default is gdb */
85: PetscSetDebugger("gdb",PETSC_TRUE);
86: #endif
87: return(0);
88: }
93: {
94: PetscTruth exists;
95: char *f;
99: PetscStrstr(string, defaultDbg, &f);
100: if (f) {
101: PetscTestFile(string, 'x', &exists);
102: if (exists) {
103: *debugger = string;
104: } else {
105: *debugger = defaultDbg;
106: }
107: }
108: return(0);
109: }
113: /*@C
114: PetscSetDebuggerFromString - Set the complete path for the
115: debugger for PETSc to use.
117: Not collective
118:
119: Level: advanced
121: .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
122: @*/
123: PetscErrorCode PetscSetDebuggerFromString(char *string)
124: {
125: const char *debugger = PETSC_NULL;
126: PetscTruth xterm = PETSC_TRUE;
127: char *f;
131: PetscStrstr(string, "noxterm", &f);
132: if (f) xterm = PETSC_FALSE;
133: PetscStrstr(string, "ddd", &f);
134: if (f) xterm = PETSC_FALSE;
146: PetscSetDebugger(debugger, xterm);
147: return(0);
148: }
153: /*@C
154: PetscAttachDebugger - Attaches the debugger to the running process.
156: Not Collective
158: Level: advanced
160: Concepts: debugger^starting from program
162: .seealso: PetscSetDebugger()
163: @*/
164: PetscErrorCode PetscAttachDebugger(void)
165: {
166: #if !defined(PETSC_CANNOT_START_DEBUGGER)
167: int child=0;
168: PetscInt sleeptime=0;
170: char program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
171: #endif
175: #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
176: (*PetscErrorPrintf)("System cannot start debugger\n");
177: (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
178: (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
179: MPI_Finalize();
180: exit(0);
181: #else
182: PetscGetDisplay(display,128);
183: PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
184: if (ierr) {
185: (*PetscErrorPrintf)("Cannot determine program name\n");
186: PetscFunctionReturn(1);
187: }
188: if (!program[0]) {
189: (*PetscErrorPrintf)("Cannot determine program name\n");
190: PetscFunctionReturn(1);
191: }
192: child = (int)fork();
193: if (child < 0) {
194: (*PetscErrorPrintf)("Error in fork() attaching debugger\n");
195: PetscFunctionReturn(1);
196: }
198: /*
199: Swap role the parent and child. This is (I think) so that control c typed
200: in the debugger goes to the correct process.
201: */
202: if (child) { child = 0; }
203: else { child = (int)getppid(); }
205: if (child) { /* I am the parent, will run the debugger */
206: const char *args[10];
207: char pid[10];
208: PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd;
210: PetscGetHostName(hostname,64);
211: /*
212: We need to send a continue signal to the "child" process on the
213: alpha, otherwise it just stays off forever
214: */
215: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
216: kill(child,SIGCONT);
217: #endif
218: sprintf(pid,"%d",child);
220: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
221: PetscStrcmp(Debugger,"ddd",&isddd);
222: PetscStrcmp(Debugger,"ups",&isups);
223: PetscStrcmp(Debugger,"xldb",&isxldb);
224: PetscStrcmp(Debugger,"xdb",&isxdb);
225: PetscStrcmp(Debugger,"dbx",&isdbx);
226: PetscStrcmp(Debugger,"idb",&isidb);
227: PetscStrcmp(Debugger,"workshop",&isworkshop);
229: if (isxxgdb || isups || isddd) {
230: args[1] = program; args[2] = pid; args[3] = "-display";
231: args[0] = Debugger; args[4] = display; args[5] = 0;
232: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
233: if (execvp(args[0],(char**)args) < 0) {
234: perror("Unable to start debugger");
235: exit(0);
236: }
237: } else if (isxldb) {
238: args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display";
239: args[0] = Debugger; args[5] = display; args[6] = 0;
240: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
241: if (execvp(args[0],(char**)args) < 0) {
242: perror("Unable to start debugger");
243: exit(0);
244: }
245: } else if (isworkshop) {
246: args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
247: args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
248: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
249: if (execvp(args[0],(char**)args) < 0) {
250: perror("Unable to start debugger");
251: exit(0);
252: }
253: } else if (!Xterm) {
254: args[1] = program; args[2] = pid; args[3] = 0;
255: args[0] = Debugger;
256: if (isidb) {
257: args[1] = "-pid";
258: args[2] = pid;
259: args[3] = "-gdb";
260: args[4] = program;
261: args[5] = 0;
262: }
263: #if defined(PETSC_USE_P_FOR_DEBUGGER)
264: if (isdbx) {
265: args[1] = "-p";
266: args[2] = pid;
267: args[3] = program;
268: args[4] = 0;
269: }
270: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
271: if (isxdb) {
272: args[1] = "-l";
273: args[2] = "ALL";
274: args[3] = "-P";
275: args[4] = pid;
276: args[5] = program;
277: args[6] = 0;
278: }
279: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
280: if (isdbx) {
281: args[1] = "-a";
282: args[2] = pid;
283: args[3] = 0;
284: }
285: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
286: if (isdbx) {
287: args[1] = "-pid";
288: args[2] = pid;
289: args[3] = program;
290: args[4] = 0;
291: }
292: #endif
293: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname);
294: if (execvp(args[0],(char**)args) < 0) {
295: perror("Unable to start debugger");
296: exit(0);
297: }
298: } else {
299: if (!display[0]) {
300: args[0] = "xterm"; args[1] = "-e";
301: args[2] = Debugger; args[3] = program;
302: args[4] = pid; args[5] = 0;
303: if (isidb) {
304: args[3] = "-gdb";
305: args[4] = pid;
306: args[5] = "-gdb";
307: args[6] = program;
308: args[7] = 0;
309: }
310: #if defined(PETSC_USE_P_FOR_DEBUGGER)
311: if (isdbx) {
312: args[3] = "-p";
313: args[4] = pid;
314: args[5] = program;
315: args[6] = 0;
316: }
317: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
318: if (isxdb) {
319: args[5] = program;
320: args[3] = "-P";
321: args[4] = pid;
322: args[6] = 0;
323: }
324: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
325: if (isdbx) {
326: args[3] = "-a";
327: args[4] = pid;
328: args[5] = 0;
329: }
330: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
331: if (isdbx) {
332: args[3] = "-pid";
333: args[4] = pid;
334: args[5] = program;
335: args[6] = 0;
336: }
337: #endif
338: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname);
339: } else {
340: args[0] = "xterm"; args[1] = "-display";
341: args[2] = display; args[3] = "-e";
342: args[4] = Debugger; args[5] = program;
343: args[6] = pid; args[7] = 0;
344: if (isidb) {
345: args[5] = "-pid";
346: args[6] = pid;
347: args[7] = "-gdb";
348: args[8] = program;
349: args[9] = 0;
350: }
351: #if defined(PETSC_USE_P_FOR_DEBUGGER)
352: if (isdbx) {
353: args[5] = "-p";
354: args[6] = pid;
355: args[7] = program;
356: args[8] = 0;
357: }
358: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
359: if (isxdb) {
360: args[7] = program;
361: args[5] = "-P";
362: args[6] = pid;
363: args[8] = 0;
364: }
365: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
366: if (isdbx) {
367: args[5] = "-a";
368: args[6] = pid;
369: args[7] = 0;
370: }
371: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
372: if (isdbx) {
373: args[5] = "-pid";
374: args[6] = pid;
375: args[7] = program;
376: args[8] = 0;
377: }
378: #endif
379: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname);
380: }
382: if (execvp("xterm",(char**)args) < 0) {
383: perror("Unable to start debugger in xterm");
384: exit(0);
385: }
386: }
387: } else { /* I am the child, continue with user code */
388: sleeptime = 10; /* default to sleep waiting for debugger */
389: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
390: if (sleeptime < 0) sleeptime = -sleeptime;
391: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
392: /*
393: HP cannot attach process to sleeping debugger, hence count instead
394: */
395: {
396: PetscReal x = 1.0;
397: int i=10000000;
398: while (i--) x++ ; /* cannot attach to sleeper */
399: }
400: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
401: /*
402: IBM sleep may return at anytime, hence must see if there is more time to sleep
403: */
404: {
405: int left = sleeptime;
406: while (left > 0) {left = PetscSleep(left) - 1;}
407: }
408: #else
409: PetscSleep(sleeptime);
410: #endif
411: }
412: #endif
413: return(0);
414: }
418: /*@C
419: PetscAttachDebuggerErrorHandler - Error handler that attaches
420: a debugger to a running process when an error is detected.
421: This routine is useful for examining variables, etc.
423: Not Collective
425: Input Parameters:
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 - the specific error number
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(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(int line,const char* fun,const char *file,const char* dir,int num,int 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) { /* hopeless so get out */
477: MPI_Finalize();
478: exit(num);
479: }
480: return(0);
481: }
485: /*@C
486: PetscStopForDebugger - Prints a message to the screen indicating how to
487: attach to the process with the debugger and then waits for the
488: debugger to attach.
490: Not Collective
492: Level: advanced
494: Concepts: debugger^waiting for attachment
496: .seealso: PetscSetDebugger(), PetscAttachDebugger()
497: @*/
498: PetscErrorCode PetscStopForDebugger(void)
499: {
501: PetscInt sleeptime=0;
502: #if !defined(PETSC_CANNOT_START_DEBUGGER)
503: int ppid;
504: PetscMPIInt rank;
505: char program[PETSC_MAX_PATH_LEN],hostname[256];
506: PetscTruth isdbx,isxldb,isxxgdb,isddd,isups,isxdb;
507: #endif
510: #if defined(PETSC_CANNOT_START_DEBUGGER)
511: (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
512: #else
513: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
514: PetscGetHostName(hostname,256);
515: if (ierr) {
516: (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
517: return(0);
518: }
520: PetscGetProgramName(program,256);
521: if (ierr) {
522: (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
523: return(0);
524: }
525: if (!program[0]) {
526: (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
527: return(0);
528: }
530: ppid = getpid();
532: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
533: PetscStrcmp(Debugger,"ddd",&isddd);
534: PetscStrcmp(Debugger,"ups",&isups);
535: PetscStrcmp(Debugger,"xldb",&isxldb);
536: PetscStrcmp(Debugger,"xdb",&isxdb);
537: PetscStrcmp(Debugger,"dbx",&isdbx);
539: if (isxxgdb || isups || isddd ) {
540: (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
541: }
542: #if defined(PETSC_USE_A_FOR_DEBUGGER)
543: else if (isxldb) {
544: (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program);
545: }
546: #endif
547: #if defined(PETSC_USE_P_FOR_DEBUGGER)
548: else if (isdbx) {
549: (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program);
550: }
551: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
552: else if (isxdb) {
553: (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program);
554: }
555: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
556: else if (isdbx) {
557: (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid);
558: }
559: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
560: else if (isdbx) {
561: (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program);
562: }
563: #else
564: else {
565: (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
566: }
567: #endif
568: #endif /* PETSC_CANNOT_START_DEBUGGER */
570: fflush(stdout);
572: sleeptime = 25; /* default to sleep waiting for debugger */
573: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
574: if (sleeptime < 0) sleeptime = -sleeptime;
575: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
576: /*
577: HP cannot attach process to sleeping debugger, hence count instead
578: */
579: {
580: PetscReal x = 1.0;
581: int i=10000000;
582: while (i--) x++ ; /* cannot attach to sleeper */
583: }
584: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
585: /*
586: IBM sleep may return at anytime, hence must see if there is more time to sleep
587: */
588: {
589: int left = sleeptime;
590: while (left > 0) {left = sleep(left) - 1;}
591: }
592: #else
593: PetscSleep(sleeptime);
594: #endif
595: return(0);
596: }