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