"Fossies" - the Fresh Open Source Software Archive

Member "petsc-3.12.3/src/sys/error/adebug.c.html" (3 Jan 2020, 49358 Bytes) of package /linux/misc/petsc-3.12.3.tar.gz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the petsc-3.12.3.tar.gz project site itself.

petsc-3.12.3 2020-01-03
Report Typos and Errors
  1: /*
  2:       Code to handle PETSc starting up in debuggers,etc.
  3: */

  5:  #include <petscsys.h>
  6: #include <signal.h>
  7: #if defined(PETSC_HAVE_UNISTD_H)
  8: #include <unistd.h>
  9: #endif

 11: /*
 12:       These are the debugger and display used if the debugger is started up
 13: */
 14: static char      PetscDebugger[PETSC_MAX_PATH_LEN];
 15: static char      DebugTerminal[PETSC_MAX_PATH_LEN];
 16: static PetscBool Xterm = PETSC_TRUE;

 18: /*@C
 19:    PetscSetDebugTerminal - Sets the terminal to use (instead of xterm) for debugging.

 21:    Not Collective

 23:    Input Parameters:
 24: .  terminal - name of terminal and any flags required to execute a program.
 25:               For example "xterm -e", "urxvt -e", "gnome-terminal -x".

 27:    Options Database Keys:
 28:    -debug_terminal terminal - use this terminal instead of xterm

 30:    Level: developer

 32:    Notes:
 33:    You can start the debugger for all processes in the same GNU screen session.

 35:      mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"

 37:    will open 4 windows in the session named "debug".

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

 42: .seealso: PetscSetDebugger()
 43: @*/
 44: PetscErrorCode  PetscSetDebugTerminal(const char terminal[])
 45: {

 49:   PetscStrcpy(DebugTerminal,terminal);
 50:   return(0);
 51: }

 53: /*@C
 54:    PetscSetDebugger - Sets options associated with the debugger.

 56:    Not Collective

 58:    Input Parameters:
 59: +  debugger - name of debugger, which should be in your path,
 60:               usually "lldb", "dbx", "gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
 61:               supports "xdb", and IBM rs6000 supports "xldb".

 63: -  xterm - flag to indicate debugger window, set to either PETSC_TRUE (to indicate
 64:             debugger should be started in a new xterm) or PETSC_FALSE (to start debugger
 65:             in initial window (the option PETSC_FALSE makes no sense when using more
 66:             than one MPI process.)

 68:    Level: developer

 70:    Fortran Note:
 71:    This routine is not supported in Fortran.

 73: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
 74: @*/
 75: PetscErrorCode  PetscSetDebugger(const char debugger[],PetscBool xterm)
 76: {

 80:   if (debugger) {
 81:     PetscStrcpy(PetscDebugger,debugger);
 82:   }
 83:   Xterm = xterm;
 84:   return(0);
 85: }

 87: /*@C
 88:     PetscSetDefaultDebugger - Causes PETSc to use its default  debugger.

 90:    Not collective

 92:     Level: developer

 94: .seealso: PetscSetDebugger(), PetscSetDebuggerFromString()
 95: @*/
 96: PetscErrorCode  PetscSetDefaultDebugger(void)
 97: {

101: #if defined(PETSC_USE_DEBUGGER)
102:   PetscSetDebugger(PETSC_USE_DEBUGGER,PETSC_TRUE);
103: #endif
104:   PetscSetDebugTerminal("xterm -e");
105:   return(0);
106: }

109: {
110:   PetscBool      exists;
111:   char           *f;

115:   PetscStrstr(string, defaultDbg, &f);
116:   if (f) {
117:     PetscTestFile(string, 'x', &exists);
118:     if (exists) *debugger = string;
119:     else        *debugger = defaultDbg;
120:   }
121:   return(0);
122: }

124: /*@C
125:     PetscSetDebuggerFromString - Set the complete path for the
126:        debugger for PETSc to use.

128:    Not collective

130:    Level: developer

132: .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
133: @*/
134: PetscErrorCode  PetscSetDebuggerFromString(const char *string)
135: {
136:   const char     *debugger = NULL;
137:   PetscBool      xterm     = PETSC_TRUE;
138:   char           *f;

142:   PetscStrstr(string, "noxterm", &f);
143:   if (f) xterm = PETSC_FALSE;
144:   PetscStrstr(string, "ddd", &f);
145:   if (f) xterm = PETSC_FALSE;

160:   PetscSetDebugger(debugger, xterm);
161:   return(0);
162: }


165: /*@
166:    PetscAttachDebugger - Attaches the debugger to the running process.

168:    Not Collective

170:    Level: advanced

172:    Developer Notes:
173:     Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()?

175: .seealso: PetscSetDebugger()
176: @*/
177: PetscErrorCode  PetscAttachDebugger(void)
178: {
179: #if !defined(PETSC_CANNOT_START_DEBUGGER)
180:   int            child    =0;
181:   PetscReal      sleeptime=0;
183:   char           program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
184: #endif

187: #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
188:   (*PetscErrorPrintf)("System cannot start debugger\n");
189:   (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
190:   (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
191:   MPI_Abort(PETSC_COMM_WORLD,1);
192: #else
193:   PetscGetDisplay(display,128);
194:   PetscGetProgramName(program,PETSC_MAX_PATH_LEN);
195:   if (ierr) {
196:     (*PetscErrorPrintf)("Cannot determine program name\n");
197:     PetscFunctionReturn(1);
198:   }
199:   if (!program[0]) {
200:     (*PetscErrorPrintf)("Cannot determine program name\n");
201:     PetscFunctionReturn(1);
202:   }
203:   child = (int)fork();
204:   if (child < 0) {
205:     (*PetscErrorPrintf)("Error in fork() attaching debugger\n");
206:     PetscFunctionReturn(1);
207:   }

209:   /*
210:       Swap role the parent and child. This is (I think) so that control c typed
211:     in the debugger goes to the correct process.
212:   */
213:   if (child) child = 0;
214:   else       child = (int)getppid();

216:   if (child) { /* I am the parent, will run the debugger */
217:     const char *args[10];
218:     char       pid[10];
219:     PetscInt   j,jj;
220:     PetscBool  isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg,islldb;

222:     PetscGetHostName(hostname,64);
223:     /*
224:          We need to send a continue signal to the "child" process on the
225:        alpha, otherwise it just stays off forever
226:     */
227: #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
228:     kill(child,SIGCONT);
229: #endif
230:     sprintf(pid,"%d",child);

232:     PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);
233:     PetscStrcmp(PetscDebugger,"ddd",&isddd);
234:     PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);
235:     PetscStrcmp(PetscDebugger,"ups",&isups);
236:     PetscStrcmp(PetscDebugger,"xldb",&isxldb);
237:     PetscStrcmp(PetscDebugger,"xdb",&isxdb);
238:     PetscStrcmp(PetscDebugger,"dbx",&isdbx);
239:     PetscStrcmp(PetscDebugger,"idb",&isidb);
240:     PetscStrcmp(PetscDebugger,"workshop",&isworkshop);
241:     PetscStrcmp(PetscDebugger,"lldb",&islldb);

243:     if (isxxgdb || isups || isddd) {
244:       args[1] = program; args[2] = pid; args[3] = "-display";
245:       args[0] = PetscDebugger; args[4] = display; args[5] = 0;
246:       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
247:       if (execvp(args[0],(char**)args)  < 0) {
248:         perror("Unable to start debugger");
249:         exit(0);
250:       }
251:     } else if (iskdbg) {
252:       args[1] = "-p"; args[2] = pid; args[3] = program;  args[4] = "-display";
253:       args[0] = PetscDebugger; args[5] = display; args[6] = 0;
254:       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname);
255:       if (execvp(args[0],(char**)args)  < 0) {
256:         perror("Unable to start debugger");
257:         exit(0);
258:       }
259:     } else if (isxldb) {
260:       args[1] = "-a"; args[2] = pid; args[3] = program;  args[4] = "-display";
261:       args[0] = PetscDebugger; args[5] = display; args[6] = 0;
262:       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
263:       if (execvp(args[0],(char**)args)  < 0) {
264:         perror("Unable to start debugger");
265:         exit(0);
266:       }
267:     } else if (isworkshop) {
268:       args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
269:       args[0] = PetscDebugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
270:       printf("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
271:       if (execvp(args[0],(char**)args)  < 0) {
272:         perror("Unable to start debugger");
273:         exit(0);
274:       }
275:     } else {
276:       j = 0;
277:       if (Xterm) {
278:         PetscBool cmp;
279:         char      *tmp,*tmp1;
280:         PetscStrncmp(DebugTerminal,"screen",6,&cmp);
281:         if (!cmp) {PetscStrncmp(DebugTerminal,"gnome-terminal",6,&cmp);}
282:         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
283:         args[j++] = tmp = DebugTerminal;
284:         if (display[0]) {
285:           args[j++] = "-display"; args[j++] = display;
286:         }
287:         while (*tmp) {
288:           PetscStrchr(tmp,' ',&tmp1);
289:           if (!tmp1) break;
290:           *tmp1     = 0;
291:           tmp       = tmp1+1;
292:           args[j++] = tmp;
293:         }
294:       }
295:       args[j++] = PetscDebugger;
296:       jj = j;
297:       args[j++] = program; args[j++] = pid; args[j++] = 0;

299:       if (isidb) {
300:         j = jj;
301:         args[j++] = "-pid";
302:         args[j++] = pid;
303:         args[j++] = "-gdb";
304:         args[j++] = program;
305:         args[j++] = 0;
306:       }
307:       if (islldb) {
308:         j = jj;
309:         args[j++] = "-p";
310:         args[j++] = pid;
311:         args[j++] = 0;
312:       }
313:       if (isdbx) {
314:         j = jj;
315: #if defined(PETSC_USE_P_FOR_DEBUGGER)
316:         args[j++] = "-p";
317:         args[j++] = pid;
318:         args[j++] = program;
319: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
320:         args[j++] = "-l";
321:         args[j++] = "ALL";
322:         args[j++] = "-P";
323:         args[j++] = pid;
324:         args[j++] = program;
325: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
326:         args[j++] = "-a";
327:         args[j++] = pid;
328: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
329:         args[j++] = "-pid";
330:         args[j++] = pid;
331:         args[j++] = program;
332: #else
333:         args[j++] = program;
334:         args[j++] = pid;
335: #endif
336:         args[j++] = 0;
337:       }
338:       if (Xterm) {
339:         if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",PetscDebugger,program,pid,display,hostname);
340:         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);

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

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

388:    Not Collective

390:    Input Parameters:
391: +  comm - communicator over which error occurred
392: .  line - the line number of the error (indicated by __LINE__)
393: .  file - the file in which the error was detected (indicated by __FILE__)
394: .  message - an error text string, usually just printed to the screen
395: .  number - the generic error number
396: .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
397: -  ctx - error handler context

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

403:    Level: developer

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

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

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


423: .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
424:            PetscAbortErrorHandler()
425: @*/
426: PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
427: {

431:   if (!fun) fun = "User provided function";
432:   if (!mess) mess = " ";

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

436:   PetscAttachDebugger();
437:   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
438:   return(0);
439: }

441: /*@C
442:    PetscStopForDebugger - Prints a message to the screen indicating how to
443:          attach to the process with the debugger and then waits for the
444:          debugger to attach.

446:    Not Collective

448:    Level: developer

450:    Notes:
451:     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.

453:    Developer Notes:
454:     Since this can be called by the error handler, should it be calling SETERRQ() and CHKERRQ()?

456: .seealso: PetscSetDebugger(), PetscAttachDebugger()
457: @*/
458: PetscErrorCode  PetscStopForDebugger(void)
459: {
461:   PetscInt       sleeptime=0;
462: #if !defined(PETSC_CANNOT_START_DEBUGGER)
463:   int            ppid;
464:   PetscMPIInt    rank;
465:   char           program[PETSC_MAX_PATH_LEN],hostname[256];
466:   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
467: #endif

470: #if defined(PETSC_CANNOT_START_DEBUGGER)
471:   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
472: #else
473:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
474:   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
475:   PetscGetHostName(hostname,256);
476:   if (ierr) {
477:     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
478:     return(0);
479:   }

481:   PetscGetProgramName(program,256);
482:   if (ierr) {
483:     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
484:     return(0);
485:   }
486:   if (!program[0]) {
487:     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
488:     return(0);
489:   }

491:   ppid = getpid();

493:   PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);
494:   PetscStrcmp(PetscDebugger,"ddd",&isddd);
495:   PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);
496:   PetscStrcmp(PetscDebugger,"ups",&isups);
497:   PetscStrcmp(PetscDebugger,"xldb",&isxldb);
498:   PetscStrcmp(PetscDebugger,"xdb",&isxdb);
499:   PetscStrcmp(PetscDebugger,"dbx",&isdbx);
500:   PetscStrcmp(PetscDebugger,"lldb",&islldb);

502:   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
503:   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
504:   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
505:   else if (isdbx) {
506: #if defined(PETSC_USE_P_FOR_DEBUGGER)
507:      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
508: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
509:      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
510: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
511:      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
512: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
513:      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
514: #else
515:      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
516: #endif
517:   }
518: #endif /* PETSC_CANNOT_START_DEBUGGER */

520:   fflush(stdout); /* ignore error because may already be in error handler */

522:   sleeptime = 25; /* default to sleep waiting for debugger */
523:   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
524:   if (sleeptime < 0) sleeptime = -sleeptime;
525: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
526:   /*
527:       HP cannot attach process to sleeping debugger, hence count instead
528:   */
529:   {
530:     PetscReal x = 1.0;
531:     int       i =10000000;
532:     while (i--) x++;  /* cannot attach to sleeper */
533:   }
534: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
535:   /*
536:       IBM sleep may return at anytime, hence must see if there is more time to sleep
537:   */
538:   {
539:     int left = sleeptime;
540:     while (left > 0) left = sleep(left) - 1;
541:   }
542: #else
543:   PetscSleep(sleeptime);
544: #endif
545:   return(0);
546: }