Actual source code: adebug.c
1: /*
2: Code to handle PETSc starting up in debuggers,etc.
3: */
4: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for fileno() */
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 UseDebugTerminal = PETSC_TRUE;
17: PetscBool petscwaitonerrorflg = PETSC_FALSE;
18: PetscBool petscindebugger = PETSC_FALSE;
20: /*@
21: PetscSetDebugTerminal - Sets the terminal to use for debugging.
23: Not Collective; No Fortran Support
25: Input Parameter:
26: . terminal - name of terminal and any flags required to execute a program.
27: For example "xterm", "urxvt -e", "gnome-terminal -x".
28: On Apple macOS you can use "Terminal" (note the capital T)
30: Options Database Key:
31: . -debug_terminal terminal - use this terminal instead of the default
33: Level: developer
35: Notes:
36: You can start the debugger for all processes in the same GNU screen session.
37: .vb
38: mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"
39: .ve
41: will open 4 windows in the session named "debug".
43: The default terminal on Apple is Terminal, on other systems the default is xterm
45: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
46: @*/
47: PetscErrorCode PetscSetDebugTerminal(const char terminal[])
48: {
49: PetscBool xterm;
51: PetscFunctionBegin;
52: PetscCall(PetscStrncpy(DebugTerminal, terminal, sizeof(DebugTerminal)));
53: PetscCall(PetscStrcmp(terminal, "xterm", &xterm));
54: if (xterm) PetscCall(PetscStrlcat(DebugTerminal, " -e", sizeof(DebugTerminal)));
55: PetscFunctionReturn(PETSC_SUCCESS);
56: }
58: /*@
59: PetscSetDebugger - Sets options associated with the debugger.
61: Not Collective; No Fortran Support
63: Input Parameters:
64: + debugger - name of debugger, which should be in your path,
65: usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
66: supports "xdb", and IBM rs6000 supports "xldb".
68: - usedebugterminal - flag to indicate debugger window, set to either `PETSC_TRUE` (to indicate
69: debugger should be started in a new terminal window) or `PETSC_FALSE` (to start debugger
70: in initial window (the option `PETSC_FALSE` makes no sense when using more
71: than one MPI process.)
73: Level: developer
75: .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
76: @*/
77: PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal)
78: {
79: PetscFunctionBegin;
80: if (debugger) PetscCall(PetscStrncpy(PetscDebugger, debugger, sizeof(PetscDebugger)));
81: if (UseDebugTerminal) UseDebugTerminal = usedebugterminal;
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: /*@
86: PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal
88: Not Collective, No Fortran Support
90: Level: developer
92: .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()`
93: @*/
94: PetscErrorCode PetscSetDefaultDebugger(void)
95: {
96: PetscFunctionBegin;
97: #if defined(PETSC_USE_DEBUGGER)
98: PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER, PETSC_TRUE));
99: #endif
100: #if defined(__APPLE__)
101: PetscCall(PetscSetDebugTerminal("Terminal"));
102: #else
103: PetscCall(PetscSetDebugTerminal("xterm"));
104: #endif
105: PetscFunctionReturn(PETSC_SUCCESS);
106: }
108: static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
109: {
110: char *f = NULL;
112: PetscFunctionBegin;
113: PetscCall(PetscStrstr(string, defaultDbg, &f));
114: if (f) {
115: PetscBool exists;
117: PetscCall(PetscTestFile(string, 'x', &exists));
118: if (exists) *debugger = string;
119: else *debugger = defaultDbg;
120: }
121: PetscFunctionReturn(PETSC_SUCCESS);
122: }
124: /*@
125: PetscSetDebuggerFromString - Set the complete path for the
126: debugger for PETSc to use.
128: Not Collective
130: Input Parameter:
131: . string - the name of the debugger, for example "gdb"
133: Level: developer
135: .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscAttachDebugger()`
136: @*/
137: PetscErrorCode PetscSetDebuggerFromString(const char string[])
138: {
139: const char *debugger = NULL;
140: PetscBool useterminal = PETSC_TRUE;
141: char *f = NULL;
143: PetscFunctionBegin;
144: PetscCall(PetscStrstr(string, "noxterm", &f));
145: if (f) useterminal = PETSC_FALSE;
146: PetscCall(PetscStrstr(string, "ddd", &f));
147: if (f) useterminal = PETSC_FALSE;
148: PetscCall(PetscStrstr(string, "noterminal", &f));
149: if (f) useterminal = PETSC_FALSE;
150: PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger));
151: PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger));
152: PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger));
153: PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger));
154: PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
155: PetscCall(PetscCheckDebugger_Private("idb", string, &debugger));
156: PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger));
157: PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger));
158: PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger));
159: PetscCall(PetscCheckDebugger_Private("ups", string, &debugger));
160: PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
161: PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger));
162: PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger));
163: PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger));
164: PetscCall(PetscSetDebugger(debugger, useterminal));
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /*@
169: PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead
170: of exiting.
172: Not Collective
174: Level: advanced
176: Note:
177: When `-start_in_debugger -debugger_ranks x,y,z` is used this prevents the processes NOT listed in x,y,z from calling `MPI_Abort()` and
178: killing the user's debugging sessions.
180: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
181: @*/
182: PetscErrorCode PetscWaitOnError(void)
183: {
184: petscwaitonerrorflg = PETSC_TRUE;
185: return PETSC_SUCCESS;
186: }
188: /*@
189: PetscAttachDebugger - Attaches the debugger to the running process.
191: Not Collective
193: Options Database Keys:
194: + -start_in_debugger [noxterm,lldb or gdb] - Set debugger debug_terminal xterm or Terminal (for Apple)
195: . -display name - XDisplay to open xterm in
196: . -debugger_ranks m,n - Which MPI ranks on which to start the debugger, defaults to all
197: . -stop_for_debugger - Print a message on how to attach the process with a debugger and then wait for the user to attach
198: - -debugger_pause <secs> - Wait <secs> before attaching the debugger. This is useful for slow connections
199: that take a long time for the Terminal window or xterm to start up.
201: Level: advanced
203: Note:
204: If you get the message "`stdin` is not a `tty`, hence unable to attach debugger, see `PetscAttachDebugger()`", this means the application
205: is likely running in a batch system and you do not have terminal access to the process. You can try
206: running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger`
208: Developer Note:
209: Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
211: .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
212: @*/
213: PetscErrorCode PetscAttachDebugger(void)
214: {
215: PetscErrorCode PETSC_UNUSED ierr;
216: #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
217: int child = 0;
218: PetscReal sleeptime = 0;
219: char program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
220: #endif
222: #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
223: ierr = (*PetscErrorPrintf)("System cannot start debugger\n");
224: ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
225: ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
226: PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
227: #else
228: if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
229: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n");
230: return PETSC_ERR_SYS;
231: }
232: if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
233: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
234: return PETSC_ERR_SYS;
235: }
236: if (PetscUnlikely(!program[0])) {
237: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
238: return PETSC_ERR_SYS;
239: }
240: if (PetscUnlikely(!isatty(fileno(stdin))) && !UseDebugTerminal) { printf("If the debugger exits immediately or hangs, this indicates you cannot use PetscAttachDebugger() in this situation\n\n"); }
241: child = fork();
242: if (PetscUnlikely(child < 0)) {
243: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n");
244: return PETSC_ERR_SYS;
245: }
246: petscindebugger = PETSC_TRUE;
248: /*
249: Swap role the parent and child. This is (I think) so that control c typed
250: in the debugger goes to the correct process.
251: */
252: #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
253: child = child ? 0 : getppid();
254: #endif
256: if (child) { /* I am the parent, will run the debugger */
257: const char *args[10];
258: char pid[10];
259: PetscInt j, jj;
260: PetscBool isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;
262: PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
263: /*
264: We need to send a continue signal to the "child" process on the
265: alpha, otherwise it just stays off forever
266: */
267: #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
268: kill(child, SIGCONT);
269: #endif
270: PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child));
272: PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
273: PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
274: PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
275: PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
276: PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
277: PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
278: PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
279: PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
280: PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
281: PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
283: if (isxxgdb || isups || isddd) {
284: args[1] = program;
285: args[2] = pid;
286: args[3] = "-display";
287: args[0] = PetscDebugger;
288: args[4] = display;
289: args[5] = NULL;
290: printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
291: if (execvp(args[0], (char **)args) < 0) {
292: perror("Unable to start debugger");
293: exit(0);
294: }
295: } else if (iskdbg) {
296: args[1] = "-p";
297: args[2] = pid;
298: args[3] = program;
299: args[4] = "-display";
300: args[0] = PetscDebugger;
301: args[5] = display;
302: args[6] = NULL;
303: printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
304: if (execvp(args[0], (char **)args) < 0) {
305: perror("Unable to start debugger");
306: exit(0);
307: }
308: } else if (isxldb) {
309: args[1] = "-a";
310: args[2] = pid;
311: args[3] = program;
312: args[4] = "-display";
313: args[0] = PetscDebugger;
314: args[5] = display;
315: args[6] = NULL;
316: printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
317: if (execvp(args[0], (char **)args) < 0) {
318: perror("Unable to start debugger");
319: exit(0);
320: }
321: } else if (isworkshop) {
322: args[1] = "-s";
323: args[2] = pid;
324: args[3] = "-D";
325: args[4] = "-";
326: args[0] = PetscDebugger;
327: args[5] = pid;
328: args[6] = "-display";
329: args[7] = display;
330: args[8] = NULL;
331: printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
332: if (execvp(args[0], (char **)args) < 0) {
333: perror("Unable to start debugger");
334: exit(0);
335: }
336: } else {
337: j = 0;
338: if (UseDebugTerminal) {
339: PetscBool cmp;
340: char *tmp, *tmp1 = NULL;
341: PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
342: if (cmp) {
343: char command[1024];
344: if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb -p %s \"'\n", pid));
345: else {
346: char fullprogram[PETSC_MAX_PATH_LEN];
347: PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
348: PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s %s %s \"'\n", PetscDebugger, fullprogram, pid));
349: }
350: #if defined(PETSC_HAVE_POPEN)
351: PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
352: #else
353: printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n");
354: #endif
355: exit(0);
356: }
358: PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp));
359: if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp));
360: if (cmp) display[0] = 0; /* when using screen, we never pass -display */
361: args[j++] = tmp = DebugTerminal;
362: if (display[0]) {
363: args[j++] = "-display";
364: args[j++] = display;
365: }
366: while (*tmp) {
367: PetscCall(PetscStrchr(tmp, ' ', &tmp1));
368: if (!tmp1) break;
369: *tmp1 = 0;
370: tmp = tmp1 + 1;
371: args[j++] = tmp;
372: }
373: }
374: args[j++] = PetscDebugger;
375: jj = j;
376: /* this is for default gdb */
377: args[j++] = program;
378: args[j++] = pid;
379: args[j++] = NULL;
381: if (isidb) {
382: j = jj;
383: args[j++] = "-pid";
384: args[j++] = pid;
385: args[j++] = "-gdb";
386: args[j++] = program;
387: args[j++] = NULL;
388: }
389: if (islldb) {
390: j = jj;
391: args[j++] = "-p";
392: args[j++] = pid;
393: args[j++] = NULL;
394: }
395: if (isdbx) {
396: j = jj;
397: #if defined(PETSC_USE_P_FOR_DEBUGGER)
398: args[j++] = "-p";
399: args[j++] = pid;
400: args[j++] = program;
401: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
402: args[j++] = "-l";
403: args[j++] = "ALL";
404: args[j++] = "-P";
405: args[j++] = pid;
406: args[j++] = program;
407: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
408: args[j++] = "-a";
409: args[j++] = pid;
410: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
411: args[j++] = "-pid";
412: args[j++] = pid;
413: args[j++] = program;
414: #else
415: args[j++] = program;
416: args[j++] = pid;
417: #endif
418: args[j++] = NULL;
419: }
420: if (UseDebugTerminal) {
421: if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n", PetscDebugger, program, pid, display, hostname);
422: else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname);
424: if (execvp(args[0], (char **)args) < 0) {
425: perror("Unable to start debugger in xterm");
426: exit(0);
427: }
428: } else {
429: printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname);
430: if (execvp(args[0], (char **)args) < 0) {
431: perror("Unable to start debugger");
432: exit(0);
433: }
434: }
435: }
436: } else { /* I am the child, continue with user code */
437: sleeptime = 10; /* default to sleep waiting for debugger */
438: PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL));
439: if (sleeptime < 0) sleeptime = -sleeptime;
440: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
441: /*
442: HP cannot attach process to sleeping debugger, hence count instead
443: */
444: {
445: PetscReal x = 1.0;
446: int i = 10000000;
447: while (i--) x++; /* cannot attach to sleeper */
448: }
449: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
450: /*
451: IBM sleep may return at anytime, hence must see if there is more time to sleep
452: */
453: {
454: int left = sleeptime;
455: while (left > 0) left = PetscSleep(left) - 1;
456: }
457: #else
458: PetscCall(PetscSleep(sleeptime));
459: #endif
460: }
461: #endif
462: return PETSC_SUCCESS;
463: }
465: /*@C
466: PetscAttachDebuggerErrorHandler - Error handler that attaches
467: a debugger to a running process when an error is detected.
468: This routine is useful for examining variables, etc.
470: Not Collective, No Fortran Support
472: Input Parameters:
473: + comm - communicator over which error occurred
474: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
475: . fun - the function name of the calling routine
476: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
477: . mess - an error text string, usually just printed to the screen
478: . num - the generic error number
479: . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
480: - ctx - error handler context
482: Level: developer
484: Notes:
485: By default the GNU debugger, gdb, is used except on macOS where lldb is used. Alternatives are cuda-gdb, lldb, dbx and
486: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
488: Most users need not directly employ this routine and the other error
489: handlers, but can instead use the simplified interface SETERR, which has
490: the calling sequence
491: .vb
492: SETERRQ(PETSC_COMM_SELF, number, p, message)
493: .ve
495: Use `PetscPushErrorHandler()` to set the desired error handler. The
496: currently available PETSc error handlers are
497: .vb
498: PetscTraceBackErrorHandler()
499: PetscAttachDebuggerErrorHandler()
500: PetscAbortErrorHandler()
501: .ve
502: or you may write your own.
504: Developer Note:
505: This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
506: causing the debugger to be attached again in a cycle.
508: .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
509: `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
510: @*/
511: PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
512: {
513: (void)comm;
514: (void)num;
515: (void)p;
516: (void)ctx;
517: if (!mess) mess = " ";
519: if (fun) (void)(*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
520: else (void)(*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
522: (void)PetscAttachDebugger();
523: abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
524: PetscFunctionReturn(PETSC_SUCCESS);
525: }
527: /*@
528: PetscStopForDebugger - Prints a message to the screen indicating how to
529: attach to the process with the debugger and then waits for the
530: debugger to attach.
532: Not Collective, No Fortran Support
534: Options Database Key:
535: . -stop_for_debugger - will stop for you to attach the debugger when `PetscInitialize()` is called
537: Level: developer
539: Note:
540: This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
542: Developer Note:
543: Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
545: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
546: @*/
547: PetscErrorCode PetscStopForDebugger(void)
548: {
549: PetscErrorCode ierr;
550: PetscInt sleeptime = 0;
551: #if !defined(PETSC_CANNOT_START_DEBUGGER)
552: int ppid;
553: PetscMPIInt rank;
554: char program[PETSC_MAX_PATH_LEN], hostname[256];
555: PetscBool isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
556: #endif
558: PetscFunctionBegin;
559: #if defined(PETSC_CANNOT_START_DEBUGGER)
560: PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"));
561: #else
562: if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */
563: ierr = PetscGetHostName(hostname, sizeof(hostname));
564: if (ierr) {
565: PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"));
566: PetscFunctionReturn(PETSC_SUCCESS);
567: }
569: ierr = PetscGetProgramName(program, sizeof(program));
570: if (ierr) {
571: PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
572: PetscFunctionReturn(PETSC_SUCCESS);
573: }
574: if (!program[0]) {
575: PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
576: PetscFunctionReturn(PETSC_SUCCESS);
577: }
579: ppid = getpid();
581: PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
582: PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
583: PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
584: PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
585: PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
586: PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
587: PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
588: PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
590: if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
591: else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
592: else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
593: else if (isdbx) {
594: #if defined(PETSC_USE_P_FOR_DEBUGGER)
595: printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
596: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
597: printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
598: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
599: printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
600: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
601: printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
602: #else
603: printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
604: #endif
605: }
606: #endif /* PETSC_CANNOT_START_DEBUGGER */
608: fflush(stdout); /* ignore error because may already be in error handler */
610: sleeptime = 25; /* default to sleep waiting for debugger */
611: PetscCallContinue(PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); /* ignore error because may already be in error handler */
612: if (sleeptime < 0) sleeptime = -sleeptime;
613: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
614: /*
615: HP cannot attach process to sleeping debugger, hence count instead
616: */
617: {
618: // this *will* get optimized away by any compiler known to man
619: PetscReal x = 1.0;
620: int i = 10000000;
621: while (i--) x++; /* cannot attach to sleeper */
622: }
623: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
624: /*
625: IBM sleep may return at anytime, hence must see if there is more time to sleep
626: */
627: {
628: int left = sleeptime;
629: while (left > 0) left = sleep(left) - 1;
630: }
631: #else
632: PetscCall(PetscSleep(sleeptime));
633: #endif
634: PetscFunctionReturn(PETSC_SUCCESS);
635: }