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