Actual source code: adebug.c

      1: #define PETSC_DLL
      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: PetscErrorCode PETSC_DLLEXPORT 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: PetscErrorCode PETSC_DLLEXPORT 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;

    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: PetscErrorCode PETSC_DLLEXPORT PetscSetDebuggerFromString(char *string)
    125: {
    126:   const char *debugger = PETSC_NULL;
    127:   PetscTruth  xterm    = PETSC_TRUE;
    128:   char       *f;

    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: PetscErrorCode PETSC_DLLEXPORT PetscAttachDebugger(void)
    166: {
    167: #if !defined(PETSC_CANNOT_START_DEBUGGER)
    168:   int            child=0;
    169:   PetscInt       sleeptime=0;
    171:   char           program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
    172: #endif

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

    199:   /*
    200:       Swap role the parent and child. This is (I think) so that control c typed
    201:     in the debugger goes to the correct process.
    202:   */
    203:   if (child) { child = 0; }
    204:   else       { child = (int)getppid(); }

    206:   if (child) { /* I am the parent, will run the debugger */
    207:     const char *args[10];
    208:     char       pid[10];
    209:     PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd;

    211:     PetscGetHostName(hostname,64);
    212:     /*
    213:          We need to send a continue signal to the "child" process on the
    214:        alpha, otherwise it just stays off forever
    215:     */
    216: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
    217:     kill(child,SIGCONT);
    218: #endif
    219:     sprintf(pid,"%d",child);

    221:     PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
    222:     PetscStrcmp(Debugger,"ddd",&isddd);
    223:     PetscStrcmp(Debugger,"ups",&isups);
    224:     PetscStrcmp(Debugger,"xldb",&isxldb);
    225:     PetscStrcmp(Debugger,"xdb",&isxdb);
    226:     PetscStrcmp(Debugger,"dbx",&isdbx);
    227:     PetscStrcmp(Debugger,"idb",&isidb);
    228:     PetscStrcmp(Debugger,"workshop",&isworkshop);

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

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

    419: /*@C
    420:    PetscAttachDebuggerErrorHandler - Error handler that attaches
    421:    a debugger to a running process when an error is detected.
    422:    This routine is useful for examining variables, etc.

    424:    Not Collective

    426:    Input Parameters:
    427: +  line - the line number of the error (indicated by __LINE__)
    428: .  fun - function where error occured (indicated by __FUNCT__)
    429: .  file - the file in which the error was detected (indicated by __FILE__)
    430: .  dir - the directory of the file (indicated by __SDIR__)
    431: .  message - an error text string, usually just printed to the screen
    432: .  number - the generic error number
    433: .  p - the specific error number
    434: -  ctx - error handler context

    436:    Options Database Keys:
    437: .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
    438:    debugger attachment

    440:    Level: developer

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

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

    451:    Notes for experienced users:
    452:    Use PetscPushErrorHandler() to set the desired error handler.  The
    453:    currently available PETSc error handlers are
    454: $    PetscTraceBackErrorHandler()
    455: $    PetscAttachDebuggerErrorHandler()
    456: $    PetscAbortErrorHandler()
    457:    or you may write your own.

    459:    Concepts: debugger^error handler
    460:    Concepts: error handler^attach debugger

    462: .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
    463:            PetscAbortErrorHandler()
    464: @*/
    465: PetscErrorCode PETSC_DLLEXPORT PetscAttachDebuggerErrorHandler(int line,const char* fun,const char *file,const char* dir,int num,int p,const char* mess,void *ctx)
    466: {

    470:   if (!fun)  fun = "User provided function";
    471:   if (!dir)  dir = " ";
    472:   if (!mess) mess = " ";

    474:   (*PetscErrorPrintf)("%s() line %d in %s%s %s\n",fun,line,dir,file,mess);

    476:   PetscAttachDebugger();
    477:   if (ierr) { /* hopeless so get out */
    478:     MPI_Finalize();
    479:     exit(num);
    480:   }
    481:   return(0);
    482: }

    486: /*@C
    487:    PetscStopForDebugger - Prints a message to the screen indicating how to
    488:          attach to the process with the debugger and then waits for the
    489:          debugger to attach.

    491:    Not Collective

    493:    Level: advanced

    495:    Concepts: debugger^waiting for attachment

    497: .seealso: PetscSetDebugger(), PetscAttachDebugger()
    498: @*/
    499: PetscErrorCode PETSC_DLLEXPORT PetscStopForDebugger(void)
    500: {
    502:   PetscInt       sleeptime=0;
    503: #if !defined(PETSC_CANNOT_START_DEBUGGER)
    504:   int            ppid;
    505:   PetscMPIInt    rank;
    506:   char           program[PETSC_MAX_PATH_LEN],hostname[256];
    507:   PetscTruth     isdbx,isxldb,isxxgdb,isddd,isups,isxdb;
    508: #endif

    511: #if defined(PETSC_CANNOT_START_DEBUGGER)
    512:   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
    513: #else
    514:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
    515:   PetscGetHostName(hostname,256);
    516:   if (ierr) {
    517:     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
    518:     return(0);
    519:   }

    521:   PetscGetProgramName(program,256);
    522:   if (ierr) {
    523:     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
    524:     return(0);
    525:   }
    526:   if (!program[0]) {
    527:     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
    528:     return(0);
    529:   }

    531:   ppid = getpid();

    533:   PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
    534:   PetscStrcmp(Debugger,"ddd",&isddd);
    535:   PetscStrcmp(Debugger,"ups",&isups);
    536:   PetscStrcmp(Debugger,"xldb",&isxldb);
    537:   PetscStrcmp(Debugger,"xdb",&isxdb);
    538:   PetscStrcmp(Debugger,"dbx",&isdbx);

    540:   if (isxxgdb || isups || isddd ) {
    541:     (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
    542:   }
    543: #if defined(PETSC_USE_A_FOR_DEBUGGER)
    544:   else if (isxldb) {
    545:     (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program);
    546:   }
    547: #endif
    548: #if defined(PETSC_USE_P_FOR_DEBUGGER)
    549:   else if (isdbx) {
    550:     (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program);
    551:   }
    552: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
    553:   else if (isxdb) {
    554:     (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program);
    555:   }
    556: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
    557:   else if (isdbx) {
    558:     (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid);
    559:   }
    560: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
    561:   else if (isdbx) {
    562:     (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program);
    563:   }
    564: #else
    565:   else {
    566:     (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
    567:   }
    568: #endif
    569: #endif /* PETSC_CANNOT_START_DEBUGGER */

    571:   fflush(stdout);

    573:   sleeptime = 25; /* default to sleep waiting for debugger */
    574:   PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
    575:   if (sleeptime < 0) sleeptime = -sleeptime;
    576: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
    577:   /*
    578:       HP cannot attach process to sleeping debugger, hence count instead
    579:   */
    580:   {
    581:     PetscReal x = 1.0;
    582:     int i=10000000;
    583:     while (i--) x++ ; /* cannot attach to sleeper */
    584:   }
    585: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
    586:   /*
    587:       IBM sleep may return at anytime, hence must see if there is more time to sleep
    588:   */
    589:   {
    590:     int left = sleeptime;
    591:     while (left > 0) {left = sleep(left) - 1;}
    592:   }
    593: #else
    594:   PetscSleep(sleeptime);
    595: #endif
    596:   return(0);
    597: }