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;

 23: #undef __FUNCT__  
 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", 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: }

 62: #undef __FUNCT__  
 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: #else  /* Default is gdb */
 84:   PetscSetDebugger("gdb",PETSC_TRUE);
 85: #endif
 86:   return(0);
 87: }

 89: #undef __FUNCT__  
 92: {
 93:   PetscTruth exists;
 94:   char      *f;
 95:   int        ierr;

 98:   PetscStrstr(string, defaultDbg, &f);
 99:   if (f) {
100:     PetscTestFile(string, 'x', &exists);
101:     if (exists) {
102:       *debugger = string;
103:     } else {
104:       *debugger = defaultDbg;
105:     }
106:   }
107:   return(0);
108: }

110: #undef __FUNCT__  
112: /*@C
113:     PetscSetDebuggerFromString - Set the complete path for the
114:        debugger for PETSc to use.

116:    Not collective
117:  
118:    Level: advanced

120: .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
121: @*/
122: int PetscSetDebuggerFromString(char *string)
123: {
124:   char      *debugger = PETSC_NULL;
125:   PetscTruth xterm    = PETSC_TRUE;
126:   char      *f;
127:   int        ierr;

130:   PetscStrstr(string, "noxterm", &f);
131:   if (f) xterm = PETSC_FALSE;
140:   PetscSetDebugger(debugger, xterm);
141:   return(0);
142: }


145: #undef __FUNCT__  
147: /*@C
148:    PetscAttachDebugger - Attaches the debugger to the running process.

150:    Not Collective

152:    Level: advanced

154:    Concepts: debugger^starting from program

156: .seealso: PetscSetDebugger()
157: @*/
158: int PetscAttachDebugger(void)
159: {
160:   int   child=0,sleeptime=0,ierr=0;
161:   char  program[PETSC_MAX_PATH_LEN],display[256],hostname[64];


165:   PetscGetDisplay(display,128);
166:   PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
167:   if (ierr) {
168:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
169:     PetscFunctionReturn(1);
170:   }

172: #if defined(PETSC_CANNOT_START_DEBUGGER) 
173:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debuggern");
174:   (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debuggern");
175:   (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)n");
176:   MPI_Finalize();
177:   exit(0);
178: #else
179:   if (!program[0]) {
180:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
181:     PetscFunctionReturn(1);
182:   }
183:   child = (int)fork();
184:   if (child < 0) {
185:     (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debuggern");
186:     PetscFunctionReturn(1);
187:   }

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

196:   if (child) { /* I am the parent, will run the debugger */
197:     char       *args[9],pid[9];
198:     PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb,isworkshop;

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

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

348:       if (execvp("xterm",args)  < 0) {
349:         perror("Unable to start debugger");
350:         exit(0);
351:       }
352:     }
353:   } else {   /* I am the child, continue with user code */
354:     sleeptime = 10; /* default to sleep waiting for debugger */
355:     PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
356:     if (sleeptime < 0) sleeptime = -sleeptime;
357: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
358:     /*
359:         HP cannot attach process to sleeping debugger, hence count instead
360:     */
361:     {
362:       PetscReal x = 1.0;
363:       int i=10000000;
364:       while (i--) x++ ; /* cannot attach to sleeper */
365:     }
366: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
367:     /*
368:         IBM sleep may return at anytime, hence must see if there is more time to sleep
369:     */
370:     {
371:       int left = sleeptime;
372:       while (left > 0) {left = PetscSleep(left) - 1;}
373:     }
374: #else
375:     PetscSleep(sleeptime);
376: #endif
377:   }
378: #endif
379:   return(0);
380: }

382: #undef __FUNCT__  
384: /*@C
385:    PetscAttachDebuggerErrorHandler - Error handler that attaches
386:    a debugger to a running process when an error is detected.
387:    This routine is useful for examining variables, etc. 

389:    Not Collective

391:    Input Parameters:
392: +  line - the line number of the error (indicated by __LINE__)
393: .  fun - function where error occured (indicated by __FUNCT__)
394: .  file - the file in which the error was detected (indicated by __FILE__)
395: .  dir - the directory of the file (indicated by __SDIR__)
396: .  message - an error text string, usually just printed to the screen
397: .  number - the generic error number
398: .  p - the specific error number
399: -  ctx - error handler context

401:    Options Database Keys:
402: .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
403:    debugger attachment

405:    Level: developer

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

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

416:    Notes for experienced users:
417:    Use PetscPushErrorHandler() to set the desired error handler.  The
418:    currently available PETSc error handlers are
419: $    PetscTraceBackErrorHandler()
420: $    PetscAttachDebuggerErrorHandler()
421: $    PetscAbortErrorHandler()
422:    or you may write your own.

424:    Concepts: debugger^error handler
425:    Concepts: error handler^attach debugger

427: .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 
428:            PetscAbortErrorHandler()
429: @*/
430: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
431: {
432:   int ierr,rank;

435:   if (!fun)  fun = "User provided function";
436:   if (!dir)  dir = " ";
437:   if (!mess) mess = " ";

439:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
440:   (*PetscErrorPrintf)("[%d]PETSC ERROR: %s() line %d in %s%s %sn",rank,fun,line,dir,file,mess);

442:   PetscAttachDebugger();
443:   if (ierr) { /* hopeless so get out */
444:     MPI_Finalize();
445:     exit(num);
446:   }
447:   return(0);
448: }

450: #undef __FUNCT__  
452: /*@C
453:    PetscStopForDebugger - Prints a message to the screen indicating how to
454:          attach to the process with the debugger and then waits for the 
455:          debugger to attach.

457:    Not Collective

459:    Level: advanced

461:    Concepts: debugger^waiting for attachment

463: .seealso: PetscSetDebugger(), PetscAttachDebugger()
464: @*/
465: int PetscStopForDebugger(void)
466: {
467:   int        sleeptime=0,ierr,ppid,rank;
468:   char       program[256],hostname[256];
469:   PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;


473:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
474:   PetscGetHostName(hostname,256);
475:   if (ierr) {
476:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing programn");
477:     return(0);
478:   }

480:   PetscGetProgramName(program,256);
481:   if (ierr) {
482:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
483:     return(0);
484:   }

486: #if defined(PETSC_CANNOT_START_DEBUGGER) 
487:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing programn");
488: #else
489:   if (!program[0]) {
490:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
491:     return(0);
492:   }

494:   ppid = getpid();

496:   PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
497:   PetscStrcmp(Debugger,"ups",&isups);
498:   PetscStrcmp(Debugger,"xldb",&isxldb);
499:   PetscStrcmp(Debugger,"xdb",&isxdb);
500:   PetscStrcmp(Debugger,"dbx",&isdbx);

502:   if (isxxgdb || isups) {
503:     (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
504:   }
505: #if defined(PETSC_USE_A_FOR_DEBUGGER)
506:   else if (isxldb) {
507:     (*PetscErrorPrintf)("{%d]%s>>%s -a %d %sn",rank,hostname,Debugger,ppid,program);
508:   }
509: #endif
510: #if defined(PETSC_USE_P_FOR_DEBUGGER)
511:   else if (isdbx) {
512:     (*PetscErrorPrintf)("[%d]%s>>%s -p %d %sn",rank,hostname,Debugger,ppid,program);
513:   }
514: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
515:   else if (isxdb) {
516:     (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %sn",rank,hostname,Debugger,ppid,program);
517:   }
518: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
519:   else if (isdbx) {
520:     (*PetscErrorPrintf)("[%d]%s>>%s -a %dn",rank,hostname,Debugger,ppid);
521:   }
522: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
523:   else if (isdbx) {
524:     (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %sn",rank,hostname,Debugger,ppid,program);
525:   }
526: #else 
527:   else {
528:     (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
529:   }
530: #endif
531: #endif /* PETSC_CANNOT_START_DEBUGGER */

533:   fflush(stdout);

535:   sleeptime = 25; /* default to sleep waiting for debugger */
536:   PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
537:   if (sleeptime < 0) sleeptime = -sleeptime;
538: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
539:   /*
540:       HP cannot attach process to sleeping debugger, hence count instead
541:   */
542:   {
543:     PetscReal x = 1.0;
544:     int i=10000000;
545:     while (i--) x++ ; /* cannot attach to sleeper */
546:   }
547: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
548:   /*
549:       IBM sleep may return at anytime, hence must see if there is more time to sleep
550:   */
551:   {
552:     int left = sleeptime;
553:     while (left > 0) {left = sleep(left) - 1;}
554:   }
555: #else
556:   PetscSleep(sleeptime);
557: #endif
558:   return(0);
559: }