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