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