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"               /*I   "petsc.h"   I*/
  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: int PetscSetDebuggerFromString(char *string)
 76: {
 77:   int        ierr;
 78:   PetscTruth xterm = PETSC_TRUE;
 79:   char       *f,*debugger = 0;

 82:   PetscStrstr(string,"noxterm",&f);
 83:   if (f) xterm = PETSC_FALSE;
 84:   PetscStrstr(string,"xdb",&f);
 85:   if (f)     debugger = "xdb";
 86:   PetscStrstr(string,"dbx",&f);
 87:   if (f)     debugger = "dbx";
 88:   PetscStrstr(string,"xldb",&f);
 89:   if (f)     debugger = "xldb";
 90:   PetscStrstr(string,"gdb",&f);
 91:   if (f)     debugger = "gdb";
 92:   PetscStrstr(string,"xxgdb",&f);
 93:   if (f)     debugger = "xxgdb";
 94:   PetscStrstr(string,"ups",&f);
 95:   if (f)     debugger = "ups";
 96:   PetscStrstr(string,"workshop",&f);
 97:   if (f)     debugger = "workshop";
 98:   PetscStrstr(string,"pgdbg",&f);
 99:   if (f)     debugger = "pgdbg";
100:   PetscSetDebugger(debugger,xterm);
101:   return(0);
102: }


105: /*@C
106:    PetscAttachDebugger - Attaches the debugger to the running process.

108:    Not Collective

110:    Level: advanced

112:    Concepts: debugger^starting from program

114: .seealso: PetscSetDebugger()
115: @*/
116: int PetscAttachDebugger(void)
117: {
118:   int   child=0,sleeptime=0,ierr=0;
119:   char  program[256],display[256],hostname[64];


123:   PetscGetDisplay(display,128);
124:   PetscGetProgramName(program,256);
125:   if (ierr) {
126:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
127:     PetscFunctionReturn(1);
128:   }

130: #if defined(PETSC_CANNOT_START_DEBUGGER) 
131:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debuggern");
132:   (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debuggern");
133:   (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)n");
134:   MPI_Finalize();
135:   exit(0);
136: #else
137:   if (!program[0]) {
138:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
139:     PetscFunctionReturn(1);
140:   }
141:   child = (int)fork();
142:   if (child < 0) {
143:     (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debuggern");
144:     PetscFunctionReturn(1);
145:   }

147:   /*
148:       Swap role the parent and child. This is (I think) so that control c typed
149:     in the debugger goes to the correct process.
150:   */
151:   if (child) { child = 0; }
152:   else       { child = (int)getppid(); }

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

158:     PetscGetHostName(hostname,64);
159:     /*
160:          We need to send a continue signal to the "child" process on the 
161:        alpha, otherwise it just stays off forever
162:     */
163: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
164:     kill(child,SIGCONT);
165: #endif
166:     sprintf(pid,"%d",child);

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

306:       if (execvp("xterm",args)  < 0) {
307:         perror("Unable to start debugger");
308:         exit(0);
309:       }
310:     }
311:   } else {   /* I am the child, continue with user code */
312:     sleeptime = 10; /* default to sleep waiting for debugger */
313:     PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
314:     if (sleeptime < 0) sleeptime = -sleeptime;
315: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
316:     /*
317:         HP cannot attach process to sleeping debugger, hence count instead
318:     */
319:     {
320:       PetscReal x = 1.0;
321:       int i=10000000;
322:       while (i--) x++ ; /* cannot attach to sleeper */
323:     }
324: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
325:     /*
326:         IBM sleep may return at anytime, hence must see if there is more time to sleep
327:     */
328:     {
329:       int left = sleeptime;
330:       while (left > 0) {left = PetscSleep(left) - 1;}
331:     }
332: #else
333:     PetscSleep(sleeptime);
334: #endif
335:   }
336: #endif
337:   return(0);
338: }

340: /*@C
341:    PetscAttachDebuggerErrorHandler - Error handler that attaches
342:    a debugger to a running process when an error is detected.
343:    This routine is useful for examining variables, etc. 

345:    Not Collective

347:    Input Parameters:
348: +  line - the line number of the error (indicated by __LINE__)
349: .  file - the file in which the error was detected (indicated by __FILE__)
350: .  dir - the directory of the file (indicated by __SDIR__)
351: .  message - an error text string, usually just printed to the screen
352: .  number - the generic error number
353: .  p - the specific error number
354: -  ctx - error handler context

356:    Options Database Keys:
357: .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
358:    debugger attachment

360:    Level: developer

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

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

371:    Notes for experienced users:
372:    Use PetscPushErrorHandler() to set the desired error handler.  The
373:    currently available PETSc error handlers are
374: $    PetscTraceBackErrorHandler()
375: $    PetscAttachDebuggerErrorHandler()
376: $    PetscAbortErrorHandler()
377:    or you may write your own.

379:    Concepts: debugger^error handler
380:    Concepts: error handler^attach debugger

382: .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 
383:            PetscAbortErrorHandler()
384: @*/
385: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
386: {
387:   int ierr,rank;

390:   if (!fun)  fun = "unknownfunction";
391:   if (!dir)  dir = " ";
392:   if (!mess) mess = " ";

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

397:   PetscAttachDebugger();
398:   if (ierr) { /* hopeless so get out */
399:     MPI_Finalize();
400:     exit(num);
401:   }
402:   return(0);
403: }

405: /*@C
406:    PetscStopForDebugger - Prints a message to the screen indicating how to
407:          attach to the process with the debugger and then waits for the 
408:          debugger to attach.

410:    Not Collective

412:    Level: advanced

414:    Concepts: debugger^waiting for attachment

416: .seealso: PetscSetDebugger(), PetscAttachDebugger()
417: @*/
418: int PetscStopForDebugger(void)
419: {
420:   int        sleeptime=0,ierr,ppid,rank;
421:   char       program[256],hostname[256];
422:   PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;


426:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
427:   PetscGetHostName(hostname,256);
428:   if (ierr) {
429:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing programn");
430:     return(0);
431:   }

433:   PetscGetProgramName(program,256);
434:   if (ierr) {
435:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
436:     return(0);
437:   }

439: #if defined(PETSC_CANNOT_START_DEBUGGER) 
440:   (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing programn");
441: #else
442:   if (!program[0]) {
443:     (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
444:     return(0);
445:   }

447:   ppid = getpid();

449:   PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
450:   PetscStrcmp(Debugger,"ups",&isups);
451:   PetscStrcmp(Debugger,"xldb",&isxldb);
452:   PetscStrcmp(Debugger,"xdb",&isxdb);
453:   PetscStrcmp(Debugger,"dbx",&isdbx);

455:   if (isxxgdb || isups) {
456:     (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
457:   }
458: #if defined(PETSC_USE_A_FOR_DEBUGGER)
459:   else if (isxldb) {
460:     (*PetscErrorPrintf)("{%d]%s>>%s -a %d %sn",rank,hostname,Debugger,ppid,program);
461:   }
462: #endif
463: #if defined(PETSC_USE_P_FOR_DEBUGGER)
464:   else if (isdbx) {
465:     (*PetscErrorPrintf)("[%d]%s>>%s -p %d %sn",rank,hostname,Debugger,ppid,program);
466:   }
467: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
468:   else if (isxdb) {
469:     (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %sn",rank,hostname,Debugger,ppid,program);
470:   }
471: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
472:   else if (isdbx) {
473:     (*PetscErrorPrintf)("[%d]%s>>%s -a %dn",rank,hostname,Debugger,ppid);
474:   }
475: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
476:   else if (isdbx) {
477:     (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %sn",rank,hostname,Debugger,ppid,program);
478:   }
479: #else 
480:   else {
481:     (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
482:   }
483: #endif
484: #endif /* PETSC_CANNOT_START_DEBUGGER */

486:   fflush(stdout);

488:   sleeptime = 25; /* default to sleep waiting for debugger */
489:   PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
490:   if (sleeptime < 0) sleeptime = -sleeptime;
491: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
492:   /*
493:       HP cannot attach process to sleeping debugger, hence count instead
494:   */
495:   {
496:     PetscReal x = 1.0;
497:     int i=10000000;
498:     while (i--) x++ ; /* cannot attach to sleeper */
499:   }
500: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
501:   /*
502:       IBM sleep may return at anytime, hence must see if there is more time to sleep
503:   */
504:   {
505:     int left = sleeptime;
506:     while (left > 0) {left = sleep(left) - 1;}
507:   }
508: #else
509:   PetscSleep(sleeptime);
510: #endif
511:   return(0);
512: }