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[256];
 21: static PetscTruth Xterm = PETSC_TRUE;

 23: /*@C
 24:    PetscSetDebugger - Sets options associated with the debugger.

 26:    Not Collective

 28:    Input Parameters:
 29: +  debugger - name of debugger, which should be in your path,
 30:               usually "dbx", "gdb", or "xxgdb".  Also, HP-UX
 31:               supports "xdb", and IBM rs6000 supports "xldb".

 33: -  xterm - flag to indicate debugger window, set to either 1 (to indicate
 34:             debugger should be started in a new xterm) or 0 (to start debugger
 35:             in initial window (the option 0 makes no sense when using more
 36:             than one processor.)

 38:    Level: developer

 40:    Fortran Note:
 41:    This routine is not supported in Fortran.

 43:   Concepts: debugger^setting

 45: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
 46: @*/
 47: int PetscSetDebugger(const char debugger[],PetscTruth xterm)
 48: {

 52:   if (debugger) {
 53:     PetscStrcpy(Debugger,debugger);
 54:   }
 55:   Xterm = xterm;

 57:   return(0);
 58: }

 60: int PetscSetDefaultDebugger(void)
 61: {

 65: #if defined(PETSC_USE_DBX_DEBUGGER)
 66:   PetscSetDebugger("dbx",PETSC_TRUE);
 67: #elif defined(PETSC_USE_XDB_DEBUGGER) 
 68:   PetscSetDebugger("xdb",PETSC_TRUE);
 69: #else  /* Default is gdb */
 70:   PetscSetDebugger("gdb",PETSC_TRUE);
 71: #endif
 72:   return(0);
 73: }

 75: static int CheckForDefaultDebugger(char *defaultDbg, char *string, char **debugger)
 76: {
 77:   PetscTruth exists;
 78:   char      *f;
 79:   int        ierr;

 82:   if (*debugger != PETSC_NULL) {
 83:     return(0);
 84:   }
 85:   PetscStrstr(string, defaultDbg, &f);
 86:   if (f) {
 87:     PetscTestFile(string, 'x', &exists);
 88:     if (exists) {
 89:       *debugger = string;
 90:     } else {
 91:       *debugger = defaultDbg;
 92:     }
 93:   }
 94:   return(0);
 95: }

 97: int PetscSetDebuggerFromString(char *string)
 98: {
 99:   char      *debugger = PETSC_NULL;
100:   PetscTruth xterm    = PETSC_TRUE;
101:   char      *f;
102:   int        ierr;

105:   PetscStrstr(string, "noxterm", &f);
106:   if (f) xterm = PETSC_FALSE;
107:   CheckForDefaultDebugger("xdb",      string, &debugger);
108:   CheckForDefaultDebugger("dbx",      string, &debugger);
109:   CheckForDefaultDebugger("xldb",     string, &debugger);
110:   CheckForDefaultDebugger("gdb",      string, &debugger);
111:   CheckForDefaultDebugger("xxgdb",    string, &debugger);
112:   CheckForDefaultDebugger("ups",      string, &debugger);
113:   CheckForDefaultDebugger("workshop", string, &debugger);
114:   CheckForDefaultDebugger("pgdbg",    string, &debugger);
115:   PetscSetDebugger(debugger, xterm);
116:   return(0);
117: }


120: /*@C
121:    PetscAttachDebugger - Attaches the debugger to the running process.

123:    Not Collective

125:    Level: advanced

127:    Concepts: debugger^starting from program

129: .seealso: PetscSetDebugger()
130: @*/
131: int PetscAttachDebugger(void)
132: {
133:   int   child=0,sleeptime=0,ierr=0;
134:   char  program[256],display[256],hostname[64];


138:   PetscGetDisplay(display,128);
139:   PetscGetProgramName(program,256);
140:   if (ierr) {
141:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
142:     PetscFunctionReturn(1);
143:   }

145: #if defined(PETSC_CANNOT_START_DEBUGGER) 
146:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debuggern");
147:   (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debuggern");
148:   (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)n");
149:   MPI_Finalize();
150:   exit(0);
151: #else
152:   if (!program[0]) {
153:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
154:     PetscFunctionReturn(1);
155:   }
156:   child = (int)fork();
157:   if (child < 0) {
158:     (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debuggern");
159:     PetscFunctionReturn(1);
160:   }

162:   /*
163:       Swap role the parent and child. This is (I think) so that control c typed
164:     in the debugger goes to the correct process.
165:   */
166:   if (child) { child = 0; }
167:   else       { child = (int)getppid(); }

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

173:     PetscGetHostName(hostname,64);
174:     /*
175:          We need to send a continue signal to the "child" process on the 
176:        alpha, otherwise it just stays off forever
177:     */
178: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
179:     kill(child,SIGCONT);
180: #endif
181:     sprintf(pid,"%d",child);

183:     PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
184:     PetscStrcmp(Debugger,"ups",&isups);
185:     PetscStrcmp(Debugger,"xldb",&isxldb);
186:     PetscStrcmp(Debugger,"xdb",&isxdb);
187:     PetscStrcmp(Debugger,"dbx",&isdbx);
188:     PetscStrcmp(Debugger,"workshop",&isworkshop);
189:     if (isxxgdb || isups) {
190:       args[1] = program; args[2] = pid; args[3] = "-display";
191:       args[0] = Debugger; args[4] = display; args[5] = 0;
192:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
193:       if (execvp(args[0],args)  < 0) {
194:         perror("Unable to start debugger");
195:         exit(0);
196:       }
197:     } else if (isxldb) {
198:       args[1] = "-a"; args[2] = pid; args[3] = program;  args[4] = "-display";
199:       args[0] = Debugger; args[5] = display; args[6] = 0;
200:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
201:       if (execvp(args[0],args)  < 0) {
202:         perror("Unable to start debugger");
203:         exit(0);
204:       }
205:     } else if (isworkshop) {
206:       args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
207:       args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
208:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %sn",args[0],pid,hostname);
209:       if (execvp(args[0],args)  < 0) {
210:         perror("Unable to start debugger");
211:         exit(0);
212:       }
213:     } else if (!Xterm) {
214:       args[1] = program; args[2] = pid; args[3] = 0;
215:       args[0] = Debugger;
216: #if defined(PETSC_USE_P_FOR_DEBUGGER)
217:       if (isdbx) {
218:         args[1] = "-p";
219:         args[2] = pid;
220:         args[3] = program;
221:         args[4] = 0;
222:       }
223: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
224:       if (isxdb) {
225:         args[1] = "-l";
226:         args[2] = "ALL";
227:         args[3] = "-P";
228:         args[4] = pid;
229:         args[5] = program;
230:         args[6] = 0;
231:       }
232: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
233:       if (isdbx) {
234:         args[1] = "-a";
235:         args[2] = pid;
236:         args[3] = 0;
237:       }
238: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
239:       if (isdbx) {
240:         args[1] = "-pid";
241:         args[2] = pid;
242:         args[3] = program;
243:         args[4] = 0;
244:       }
245: #endif
246:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %sn",Debugger,program,pid,hostname);
247:       if (execvp(args[0],args)  < 0) {
248:         perror("Unable to start debugger");
249:         exit(0);
250:       }
251:     } else {
252:       if (!display[0]) {
253:         args[0] = "xterm";  args[1] = "-e";
254:         args[2] = Debugger; args[3] = program;
255:         args[4] = pid;      args[5] = 0;
256: #if defined(PETSC_USE_P_FOR_DEBUGGER)
257:         if (isdbx) {
258:           args[3] = "-p";
259:           args[4] = pid;
260:           args[5] = program;
261:           args[6] = 0;
262:         }
263: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
264:         if (isxdb) {
265:           args[5] = program;
266:           args[3] = "-P";
267:           args[4] = pid;
268:           args[6] = 0;
269:         }
270: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
271:         if (isdbx) {
272:           args[3] = "-a";
273:           args[4] = pid;
274:           args[5] = 0;
275:         }
276: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
277:       if (isdbx) {
278:         args[3] = "-pid";
279:         args[4] = pid;
280:         args[5] = program;
281:         args[6] = 0;
282:       }
283: #endif
284:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %sn",Debugger,program,pid,hostname);
285:       } else {
286:         args[0] = "xterm";  args[1] = "-display";
287:         args[2] = display;  args[3] = "-e";
288:         args[4] = Debugger; args[5] = program;
289:         args[6] = pid;      args[7] = 0;
290: #if defined(PETSC_USE_P_FOR_DEBUGGER)
291:         if (isdbx) {
292:           args[5] = "-p";
293:           args[6] = pid;
294:           args[7] = program;
295:           args[8] = 0;
296:         }
297: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
298:         if (isxdb) {
299:           args[7] = program;
300:           args[5] = "-P";
301:           args[6] = pid;
302:           args[8] = 0;
303:         }
304: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
305:         if (isdbx) {
306:           args[5] = "-a";
307:           args[6] = pid;
308:           args[7] = 0;
309:         }
310: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
311:       if (isdbx) {
312:         args[5] = "-pid";
313:         args[6] = pid;
314:         args[7] = program;
315:         args[8] = 0;
316:       }
317: #endif
318:       (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %sn",Debugger,program,pid,display,hostname);
319:       }

321:       if (execvp("xterm",args)  < 0) {
322:         perror("Unable to start debugger");
323:         exit(0);
324:       }
325:     }
326:   } else {   /* I am the child, continue with user code */
327:     sleeptime = 10; /* default to sleep waiting for debugger */
328:     PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
329:     if (sleeptime < 0) sleeptime = -sleeptime;
330: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
331:     /*
332:         HP cannot attach process to sleeping debugger, hence count instead
333:     */
334:     {
335:       PetscReal x = 1.0;
336:       int i=10000000;
337:       while (i--) x++ ; /* cannot attach to sleeper */
338:     }
339: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
340:     /*
341:         IBM sleep may return at anytime, hence must see if there is more time to sleep
342:     */
343:     {
344:       int left = sleeptime;
345:       while (left > 0) {left = PetscSleep(left) - 1;}
346:     }
347: #else
348:     PetscSleep(sleeptime);
349: #endif
350:   }
351: #endif
352:   return(0);
353: }

355: /*@C
356:    PetscAttachDebuggerErrorHandler - Error handler that attaches
357:    a debugger to a running process when an error is detected.
358:    This routine is useful for examining variables, etc. 

360:    Not Collective

362:    Input Parameters:
363: +  line - the line number of the error (indicated by __LINE__)
364: .  file - the file in which the error was detected (indicated by __FILE__)
365: .  dir - the directory of the file (indicated by __SDIR__)
366: .  message - an error text string, usually just printed to the screen
367: .  number - the generic error number
368: .  p - the specific error number
369: -  ctx - error handler context

371:    Options Database Keys:
372: .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
373:    debugger attachment

375:    Level: developer

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

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

386:    Notes for experienced users:
387:    Use PetscPushErrorHandler() to set the desired error handler.  The
388:    currently available PETSc error handlers are
389: $    PetscTraceBackErrorHandler()
390: $    PetscAttachDebuggerErrorHandler()
391: $    PetscAbortErrorHandler()
392:    or you may write your own.

394:    Concepts: debugger^error handler
395:    Concepts: error handler^attach debugger

397: .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 
398:            PetscAbortErrorHandler()
399: @*/
400: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
401: {
402:   int ierr,rank;

405:   if (!fun)  fun = "unknownfunction";
406:   if (!dir)  dir = " ";
407:   if (!mess) mess = " ";

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

412:   PetscAttachDebugger();
413:   if (ierr) { /* hopeless so get out */
414:     MPI_Finalize();
415:     exit(num);
416:   }
417:   return(0);
418: }

420: /*@C
421:    PetscStopForDebugger - Prints a message to the screen indicating how to
422:          attach to the process with the debugger and then waits for the 
423:          debugger to attach.

425:    Not Collective

427:    Level: advanced

429:    Concepts: debugger^waiting for attachment

431: .seealso: PetscSetDebugger(), PetscAttachDebugger()
432: @*/
433: int PetscStopForDebugger(void)
434: {
435:   int        sleeptime=0,ierr,ppid,rank;
436:   char       program[256],hostname[256];
437:   PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;


441:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
442:   PetscGetHostName(hostname,256);
443:   if (ierr) {
444:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing programn");
445:     return(0);
446:   }

448:   PetscGetProgramName(program,256);
449:   if (ierr) {
450:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
451:     return(0);
452:   }

454: #if defined(PETSC_CANNOT_START_DEBUGGER) 
455:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing programn");
456: #else
457:   if (!program[0]) {
458:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
459:     return(0);
460:   }

462:   ppid = getpid();

464:   PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
465:   PetscStrcmp(Debugger,"ups",&isups);
466:   PetscStrcmp(Debugger,"xldb",&isxldb);
467:   PetscStrcmp(Debugger,"xdb",&isxdb);
468:   PetscStrcmp(Debugger,"dbx",&isdbx);

470:   if (isxxgdb || isups) {
471:     (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
472:   }
473: #if defined(PETSC_USE_A_FOR_DEBUGGER)
474:   else if (isxldb) {
475:     (*PetscErrorPrintf)("{%d]%s>>%s -a %d %sn",rank,hostname,Debugger,ppid,program);
476:   }
477: #endif
478: #if defined(PETSC_USE_P_FOR_DEBUGGER)
479:   else if (isdbx) {
480:     (*PetscErrorPrintf)("[%d]%s>>%s -p %d %sn",rank,hostname,Debugger,ppid,program);
481:   }
482: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
483:   else if (isxdb) {
484:     (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %sn",rank,hostname,Debugger,ppid,program);
485:   }
486: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
487:   else if (isdbx) {
488:     (*PetscErrorPrintf)("[%d]%s>>%s -a %dn",rank,hostname,Debugger,ppid);
489:   }
490: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
491:   else if (isdbx) {
492:     (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %sn",rank,hostname,Debugger,ppid,program);
493:   }
494: #else 
495:   else {
496:     (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
497:   }
498: #endif
499: #endif /* PETSC_CANNOT_START_DEBUGGER */

501:   fflush(stdout);

503:   sleeptime = 25; /* default to sleep waiting for debugger */
504:   PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
505:   if (sleeptime < 0) sleeptime = -sleeptime;
506: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
507:   /*
508:       HP cannot attach process to sleeping debugger, hence count instead
509:   */
510:   {
511:     PetscReal x = 1.0;
512:     int i=10000000;
513:     while (i--) x++ ; /* cannot attach to sleeper */
514:   }
515: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
516:   /*
517:       IBM sleep may return at anytime, hence must see if there is more time to sleep
518:   */
519:   {
520:     int left = sleeptime;
521:     while (left > 0) {left = sleep(left) - 1;}
522:   }
523: #else
524:   PetscSleep(sleeptime);
525: #endif
526:   return(0);
527: }