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" or "xxgdb".  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:   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;
143:   PetscSetDebugger(debugger, xterm);
144:   return(0);
145: }


150: /*@C
151:    PetscAttachDebugger - Attaches the debugger to the running process.

153:    Not Collective

155:    Level: advanced

157:    Concepts: debugger^starting from program

159: .seealso: PetscSetDebugger()
160: @*/
161: int PetscAttachDebugger(void)
162: {
163: #if !defined(PETSC_CANNOT_START_DEBUGGER) 
164:   int   child=0,sleeptime=0,ierr=0;
165:   char  program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
166: #endif


170: #if defined(PETSC_CANNOT_START_DEBUGGER )
171:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger\n");
172:   (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debugger\n");
173:   (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)\n");
174:   MPI_Finalize();
175:   exit(0);
176: #else
177:   PetscGetDisplay(display,128);
178:   PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
179:   if (ierr) {
180:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name\n");
181:     PetscFunctionReturn(1);
182:   }
183:   if (!program[0]) {
184:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name\n");
185:     PetscFunctionReturn(1);
186:   }
187:   child = (int)fork();
188:   if (child < 0) {
189:     (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debugger\n");
190:     PetscFunctionReturn(1);
191:   }

193:   /*
194:       Swap role the parent and child. This is (I think) so that control c typed
195:     in the debugger goes to the correct process.
196:   */
197:   if (child) { child = 0; }
198:   else       { child = (int)getppid(); }

200:   if (child) { /* I am the parent, will run the debugger */
201:     char       *args[10],pid[10];
202:     PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop;

204:     PetscGetHostName(hostname,64);
205:     /*
206:          We need to send a continue signal to the "child" process on the 
207:        alpha, otherwise it just stays off forever
208:     */
209: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
210:     kill(child,SIGCONT);
211: #endif
212:     sprintf(pid,"%d",child);

214:     PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
215:     PetscStrcmp(Debugger,"ups",&isups);
216:     PetscStrcmp(Debugger,"xldb",&isxldb);
217:     PetscStrcmp(Debugger,"xdb",&isxdb);
218:     PetscStrcmp(Debugger,"dbx",&isdbx);
219:     PetscStrcmp(Debugger,"idb",&isidb);
220:     PetscStrcmp(Debugger,"workshop",&isworkshop);
221:     if (isxxgdb || isups) {
222:       args[1] = program; args[2] = pid; args[3] = "-display";
223:       args[0] = Debugger; args[4] = display; args[5] = 0;
224:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
225:       if (execvp(args[0],args)  < 0) {
226:         perror("Unable to start debugger");
227:         exit(0);
228:       }
229:     } else if (isxldb) {
230:       args[1] = "-a"; args[2] = pid; args[3] = program;  args[4] = "-display";
231:       args[0] = Debugger; args[5] = display; args[6] = 0;
232:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
233:       if (execvp(args[0],args)  < 0) {
234:         perror("Unable to start debugger");
235:         exit(0);
236:       }
237:     } else if (isworkshop) {
238:       args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
239:       args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
240:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
241:       if (execvp(args[0],args)  < 0) {
242:         perror("Unable to start debugger");
243:         exit(0);
244:       }
245:     } else if (!Xterm) {
246:       args[1] = program; args[2] = pid; args[3] = 0;
247:       args[0] = Debugger;
248:       if (isidb) {
249:         args[1] = "-pid";
250:         args[2] = pid;
251:         args[3] = "-gdb";
252:         args[4] = program;
253:         args[5] = 0;
254:       }
255: #if defined(PETSC_USE_P_FOR_DEBUGGER)
256:       if (isdbx) {
257:         args[1] = "-p";
258:         args[2] = pid;
259:         args[3] = program;
260:         args[4] = 0;
261:       }
262: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
263:       if (isxdb) {
264:         args[1] = "-l";
265:         args[2] = "ALL";
266:         args[3] = "-P";
267:         args[4] = pid;
268:         args[5] = program;
269:         args[6] = 0;
270:       }
271: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
272:       if (isdbx) {
273:         args[1] = "-a";
274:         args[2] = pid;
275:         args[3] = 0;
276:       }
277: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
278:       if (isdbx) {
279:         args[1] = "-pid";
280:         args[2] = pid;
281:         args[3] = program;
282:         args[4] = 0;
283:       }
284: #endif
285:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname);
286:       if (execvp(args[0],args)  < 0) {
287:         perror("Unable to start debugger");
288:         exit(0);
289:       }
290:     } else {
291:       if (!display[0]) {
292:         args[0] = "xterm";  args[1] = "-e";
293:         args[2] = Debugger; args[3] = program;
294:         args[4] = pid;      args[5] = 0;
295:         if (isidb) {
296:           args[3] = "-gdb";
297:           args[4] = pid;
298:           args[5] = "-gdb";
299:           args[6] = program;
300:           args[7] = 0;
301:         }
302: #if defined(PETSC_USE_P_FOR_DEBUGGER)
303:         if (isdbx) {
304:           args[3] = "-p";
305:           args[4] = pid;
306:           args[5] = program;
307:           args[6] = 0;
308:         }
309: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
310:         if (isxdb) {
311:           args[5] = program;
312:           args[3] = "-P";
313:           args[4] = pid;
314:           args[6] = 0;
315:         }
316: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
317:         if (isdbx) {
318:           args[3] = "-a";
319:           args[4] = pid;
320:           args[5] = 0;
321:         }
322: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
323:       if (isdbx) {
324:         args[3] = "-pid";
325:         args[4] = pid;
326:         args[5] = program;
327:         args[6] = 0;
328:       }
329: #endif
330:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname);
331:       } else {
332:         args[0] = "xterm";  args[1] = "-display";
333:         args[2] = display;  args[3] = "-e";
334:         args[4] = Debugger; args[5] = program;
335:         args[6] = pid;      args[7] = 0;
336:         if (isidb) {
337:           args[5] = "-pid";
338:           args[6] = pid;
339:           args[7] = "-gdb";
340:           args[8] = program;
341:           args[9] = 0;
342:         }
343: #if defined(PETSC_USE_P_FOR_DEBUGGER)
344:         if (isdbx) {
345:           args[5] = "-p";
346:           args[6] = pid;
347:           args[7] = program;
348:           args[8] = 0;
349:         }
350: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
351:         if (isxdb) {
352:           args[7] = program;
353:           args[5] = "-P";
354:           args[6] = pid;
355:           args[8] = 0;
356:         }
357: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
358:         if (isdbx) {
359:           args[5] = "-a";
360:           args[6] = pid;
361:           args[7] = 0;
362:         }
363: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
364:       if (isdbx) {
365:         args[5] = "-pid";
366:         args[6] = pid;
367:         args[7] = program;
368:         args[8] = 0;
369:       }
370: #endif
371:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname);
372:       }

374:       if (execvp("xterm",args)  < 0) {
375:         perror("Unable to start debugger");
376:         exit(0);
377:       }
378:     }
379:   } else {   /* I am the child, continue with user code */
380:     sleeptime = 10; /* default to sleep waiting for debugger */
381:     PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
382:     if (sleeptime < 0) sleeptime = -sleeptime;
383: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
384:     /*
385:         HP cannot attach process to sleeping debugger, hence count instead
386:     */
387:     {
388:       PetscReal x = 1.0;
389:       int i=10000000;
390:       while (i--) x++ ; /* cannot attach to sleeper */
391:     }
392: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
393:     /*
394:         IBM sleep may return at anytime, hence must see if there is more time to sleep
395:     */
396:     {
397:       int left = sleeptime;
398:       while (left > 0) {left = PetscSleep(left) - 1;}
399:     }
400: #else
401:     PetscSleep(sleeptime);
402: #endif
403:   }
404: #endif
405:   return(0);
406: }

410: /*@C
411:    PetscAttachDebuggerErrorHandler - Error handler that attaches
412:    a debugger to a running process when an error is detected.
413:    This routine is useful for examining variables, etc. 

415:    Not Collective

417:    Input Parameters:
418: +  line - the line number of the error (indicated by __LINE__)
419: .  fun - function where error occured (indicated by __FUNCT__)
420: .  file - the file in which the error was detected (indicated by __FILE__)
421: .  dir - the directory of the file (indicated by __SDIR__)
422: .  message - an error text string, usually just printed to the screen
423: .  number - the generic error number
424: .  p - the specific error number
425: -  ctx - error handler context

427:    Options Database Keys:
428: .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
429:    debugger attachment

431:    Level: developer

433:    Notes:
434:    By default the GNU debugger, gdb, is used.  Alternatives are dbx and
435:    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).

437:    Most users need not directly employ this routine and the other error 
438:    handlers, but can instead use the simplified interface SETERR, which has 
439:    the calling sequence
440: $     SETERRQ(number,p,message)

442:    Notes for experienced users:
443:    Use PetscPushErrorHandler() to set the desired error handler.  The
444:    currently available PETSc error handlers are
445: $    PetscTraceBackErrorHandler()
446: $    PetscAttachDebuggerErrorHandler()
447: $    PetscAbortErrorHandler()
448:    or you may write your own.

450:    Concepts: debugger^error handler
451:    Concepts: error handler^attach debugger

453: .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 
454:            PetscAbortErrorHandler()
455: @*/
456: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
457: {
458:   int ierr,rank;

461:   if (!fun)  fun = "User provided function";
462:   if (!dir)  dir = " ";
463:   if (!mess) mess = " ";

465:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
466:   (*PetscErrorPrintf)("[%d]PETSC ERROR: %s() line %d in %s%s %s\n",rank,fun,line,dir,file,mess);

468:   PetscAttachDebugger();
469:   if (ierr) { /* hopeless so get out */
470:     MPI_Finalize();
471:     exit(num);
472:   }
473:   return(0);
474: }

478: /*@C
479:    PetscStopForDebugger - Prints a message to the screen indicating how to
480:          attach to the process with the debugger and then waits for the 
481:          debugger to attach.

483:    Not Collective

485:    Level: advanced

487:    Concepts: debugger^waiting for attachment

489: .seealso: PetscSetDebugger(), PetscAttachDebugger()
490: @*/
491: int PetscStopForDebugger(void)
492: {
493:   int        ierr,sleeptime=0;
494: #if !defined(PETSC_CANNOT_START_DEBUGGER) 
495:   int        ppid,rank;
496:   char       program[256],hostname[256];
497:   PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;
498: #endif

501: #if defined(PETSC_CANNOT_START_DEBUGGER) 
502:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing program\n");
503: #else
504:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
505:   PetscGetHostName(hostname,256);
506:   if (ierr) {
507:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing program\n");
508:     return(0);
509:   }

511:   PetscGetProgramName(program,256);
512:   if (ierr) {
513:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing program\n");
514:     return(0);
515:   }
516:   if (!program[0]) {
517:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing program\n");
518:     return(0);
519:   }

521:   ppid = getpid();

523:   PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
524:   PetscStrcmp(Debugger,"ups",&isups);
525:   PetscStrcmp(Debugger,"xldb",&isxldb);
526:   PetscStrcmp(Debugger,"xdb",&isxdb);
527:   PetscStrcmp(Debugger,"dbx",&isdbx);

529:   if (isxxgdb || isups) {
530:     (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
531:   }
532: #if defined(PETSC_USE_A_FOR_DEBUGGER)
533:   else if (isxldb) {
534:     (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program);
535:   }
536: #endif
537: #if defined(PETSC_USE_P_FOR_DEBUGGER)
538:   else if (isdbx) {
539:     (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program);
540:   }
541: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
542:   else if (isxdb) {
543:     (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program);
544:   }
545: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
546:   else if (isdbx) {
547:     (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid);
548:   }
549: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
550:   else if (isdbx) {
551:     (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program);
552:   }
553: #else 
554:   else {
555:     (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
556:   }
557: #endif
558: #endif /* PETSC_CANNOT_START_DEBUGGER */

560:   fflush(stdout);

562:   sleeptime = 25; /* default to sleep waiting for debugger */
563:   PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
564:   if (sleeptime < 0) sleeptime = -sleeptime;
565: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
566:   /*
567:       HP cannot attach process to sleeping debugger, hence count instead
568:   */
569:   {
570:     PetscReal x = 1.0;
571:     int i=10000000;
572:     while (i--) x++ ; /* cannot attach to sleeper */
573:   }
574: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
575:   /*
576:       IBM sleep may return at anytime, hence must see if there is more time to sleep
577:   */
578:   {
579:     int left = sleeptime;
580:     while (left > 0) {left = sleep(left) - 1;}
581:   }
582: #else
583:   PetscSleep(sleeptime);
584: #endif
585:   return(0);
586: }