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: }