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