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: /*@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()`, `PetscAttachDebugger()`
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()`, `PetscAttachDebugger()`
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: Input Parameter:
130: . string - the name of the debugger, for example "gdb"
132: Level: developer
134: .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscAttachDebugger()`
135: @*/
136: PetscErrorCode PetscSetDebuggerFromString(const char *string)
137: {
138: const char *debugger = NULL;
139: PetscBool useterminal = PETSC_TRUE;
140: char *f = NULL;
142: PetscFunctionBegin;
143: PetscCall(PetscStrstr(string, "noxterm", &f));
144: if (f) useterminal = PETSC_FALSE;
145: PetscCall(PetscStrstr(string, "ddd", &f));
146: if (f) useterminal = PETSC_FALSE;
147: PetscCall(PetscStrstr(string, "noterminal", &f));
148: if (f) useterminal = PETSC_FALSE;
149: PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger));
150: PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger));
151: PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger));
152: PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger));
153: PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
154: PetscCall(PetscCheckDebugger_Private("idb", string, &debugger));
155: PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger));
156: PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger));
157: PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger));
158: PetscCall(PetscCheckDebugger_Private("ups", string, &debugger));
159: PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
160: PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger));
161: PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger));
162: PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger));
163: PetscCall(PetscSetDebugger(debugger, useterminal));
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*@
168: PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead
169: of exiting.
171: Not Collective
173: Level: advanced
175: Note:
176: 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
177: killing the user's debugging sessions.
179: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
180: @*/
181: PetscErrorCode PetscWaitOnError(void)
182: {
183: petscwaitonerrorflg = PETSC_TRUE;
184: return PETSC_SUCCESS;
185: }
187: /*@
188: PetscAttachDebugger - Attaches the debugger to the running process.
190: Not Collective
192: Options Database Keys:
193: + -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n] - set debugger debug_terminal xterm or Terminal (for Apple)
194: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
195: - -stop_for_debugger - print a message on how to attach the process with a debugger and then wait for the user to attach
197: Level: advanced
199: Note:
200: If you get the message " stdin is not a tty, hence unable to attach debugger, see PetscAttachDebugger()", this means the application
201: is likely running in a batch system and you do not have terminal access to the process. You can try
202: running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger`
204: Developer Notes:
205: Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
207: .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
208: @*/
209: PetscErrorCode PetscAttachDebugger(void)
210: {
211: PetscErrorCode PETSC_UNUSED ierr;
212: #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
213: int child = 0;
214: PetscReal sleeptime = 0;
215: char program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
216: #endif
218: #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
219: ierr = (*PetscErrorPrintf)("System cannot start debugger\n");
220: ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
221: ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
222: PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
223: #else
224: if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
225: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n");
226: return PETSC_ERR_SYS;
227: }
228: if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
229: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
230: return PETSC_ERR_SYS;
231: }
232: if (PetscUnlikely(!program[0])) {
233: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
234: return PETSC_ERR_SYS;
235: }
236: 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"); }
237: child = (int)fork();
238: if (PetscUnlikely(child < 0)) {
239: ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n");
240: return PETSC_ERR_SYS;
241: }
242: petscindebugger = PETSC_TRUE;
244: /*
245: Swap role the parent and child. This is (I think) so that control c typed
246: in the debugger goes to the correct process.
247: */
248: #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
249: child = child ? 0 : (int)getppid();
250: #endif
252: if (child) { /* I am the parent, will run the debugger */
253: const char *args[10];
254: char pid[10];
255: PetscInt j, jj;
256: PetscBool isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;
258: PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
259: /*
260: We need to send a continue signal to the "child" process on the
261: alpha, otherwise it just stays off forever
262: */
263: #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
264: kill(child, SIGCONT);
265: #endif
266: PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child));
268: PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
269: PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
270: PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
271: PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
272: PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
273: PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
274: PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
275: PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
276: PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
277: PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
279: if (isxxgdb || isups || isddd) {
280: args[1] = program;
281: args[2] = pid;
282: args[3] = "-display";
283: args[0] = PetscDebugger;
284: args[4] = display;
285: args[5] = NULL;
286: printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
287: if (execvp(args[0], (char **)args) < 0) {
288: perror("Unable to start debugger");
289: exit(0);
290: }
291: } else if (iskdbg) {
292: args[1] = "-p";
293: args[2] = pid;
294: args[3] = program;
295: args[4] = "-display";
296: args[0] = PetscDebugger;
297: args[5] = display;
298: args[6] = NULL;
299: printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
300: if (execvp(args[0], (char **)args) < 0) {
301: perror("Unable to start debugger");
302: exit(0);
303: }
304: } else if (isxldb) {
305: args[1] = "-a";
306: args[2] = pid;
307: args[3] = program;
308: args[4] = "-display";
309: args[0] = PetscDebugger;
310: args[5] = display;
311: args[6] = NULL;
312: printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
313: if (execvp(args[0], (char **)args) < 0) {
314: perror("Unable to start debugger");
315: exit(0);
316: }
317: } else if (isworkshop) {
318: args[1] = "-s";
319: args[2] = pid;
320: args[3] = "-D";
321: args[4] = "-";
322: args[0] = PetscDebugger;
323: args[5] = pid;
324: args[6] = "-display";
325: args[7] = display;
326: args[8] = NULL;
327: printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
328: if (execvp(args[0], (char **)args) < 0) {
329: perror("Unable to start debugger");
330: exit(0);
331: }
332: } else {
333: j = 0;
334: if (UseDebugTerminal) {
335: PetscBool cmp;
336: char *tmp, *tmp1 = NULL;
337: PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
338: if (cmp) {
339: char command[1024];
340: if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb -p %s \"'\n", pid));
341: else {
342: char fullprogram[PETSC_MAX_PATH_LEN];
343: PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
344: PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s %s %s \"'\n", PetscDebugger, fullprogram, pid));
345: }
346: #if defined(PETSC_HAVE_POPEN)
347: PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
348: #else
349: printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n");
350: #endif
351: exit(0);
352: }
354: PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp));
355: if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp));
356: if (cmp) display[0] = 0; /* when using screen, we never pass -display */
357: args[j++] = tmp = DebugTerminal;
358: if (display[0]) {
359: args[j++] = "-display";
360: args[j++] = display;
361: }
362: while (*tmp) {
363: PetscCall(PetscStrchr(tmp, ' ', &tmp1));
364: if (!tmp1) break;
365: *tmp1 = 0;
366: tmp = tmp1 + 1;
367: args[j++] = tmp;
368: }
369: }
370: args[j++] = PetscDebugger;
371: jj = j;
372: /* this is for default gdb */
373: args[j++] = program;
374: args[j++] = pid;
375: args[j++] = NULL;
377: if (isidb) {
378: j = jj;
379: args[j++] = "-pid";
380: args[j++] = pid;
381: args[j++] = "-gdb";
382: args[j++] = program;
383: args[j++] = NULL;
384: }
385: if (islldb) {
386: j = jj;
387: args[j++] = "-p";
388: args[j++] = pid;
389: args[j++] = NULL;
390: }
391: if (isdbx) {
392: j = jj;
393: #if defined(PETSC_USE_P_FOR_DEBUGGER)
394: args[j++] = "-p";
395: args[j++] = pid;
396: args[j++] = program;
397: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
398: args[j++] = "-l";
399: args[j++] = "ALL";
400: args[j++] = "-P";
401: args[j++] = pid;
402: args[j++] = program;
403: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
404: args[j++] = "-a";
405: args[j++] = pid;
406: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
407: args[j++] = "-pid";
408: args[j++] = pid;
409: args[j++] = program;
410: #else
411: args[j++] = program;
412: args[j++] = pid;
413: #endif
414: args[j++] = NULL;
415: }
416: if (UseDebugTerminal) {
417: if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n", PetscDebugger, program, pid, display, hostname);
418: else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname);
420: if (execvp(args[0], (char **)args) < 0) {
421: perror("Unable to start debugger in xterm");
422: exit(0);
423: }
424: } else {
425: printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname);
426: if (execvp(args[0], (char **)args) < 0) {
427: perror("Unable to start debugger");
428: exit(0);
429: }
430: }
431: }
432: } else { /* I am the child, continue with user code */
433: sleeptime = 10; /* default to sleep waiting for debugger */
434: PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL));
435: if (sleeptime < 0) sleeptime = -sleeptime;
436: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
437: /*
438: HP cannot attach process to sleeping debugger, hence count instead
439: */
440: {
441: PetscReal x = 1.0;
442: int i = 10000000;
443: while (i--) x++; /* cannot attach to sleeper */
444: }
445: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
446: /*
447: IBM sleep may return at anytime, hence must see if there is more time to sleep
448: */
449: {
450: int left = sleeptime;
451: while (left > 0) left = PetscSleep(left) - 1;
452: }
453: #else
454: PetscCall(PetscSleep(sleeptime));
455: #endif
456: }
457: #endif
458: return PETSC_SUCCESS;
459: }
461: /*@C
462: PetscAttachDebuggerErrorHandler - Error handler that attaches
463: a debugger to a running process when an error is detected.
464: This routine is useful for examining variables, etc.
466: Not Collective
468: Input Parameters:
469: + comm - communicator over which error occurred
470: . line - the line number of the error (indicated by `__LINE__`)
471: . fun - the function name
472: . file - the file in which the error was detected (indicated by `__FILE__`)
473: . mess - an error text string, usually just printed to the screen
474: . num - the generic error number
475: . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
476: - ctx - error handler context
478: Level: developer
480: Notes:
481: By default the Gnu debugger, gdb, is used. Alternatives are cuda-gdb, lldb, dbx and
482: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
484: Most users need not directly employ this routine and the other error
485: handlers, but can instead use the simplified interface SETERR, which has
486: the calling sequence
487: $ SETERRQ(PETSC_COMM_SELF, number, p, message)
489: Notes for experienced users:
490: Use `PetscPushErrorHandler()` to set the desired error handler. The
491: currently available PETSc error handlers are
492: .vb
493: PetscTraceBackErrorHandler()
494: PetscAttachDebuggerErrorHandler()
495: PetscAbortErrorHandler()
496: .ve
497: or you may write your own.
499: Developer Notes:
500: This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
501: causing the debugger to be attached again in a cycle.
503: .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
504: `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
505: @*/
506: PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
507: {
508: PetscErrorCode ierr;
510: (void)comm;
511: (void)num;
512: (void)p;
513: (void)ctx;
514: if (!mess) mess = " ";
516: if (fun) ierr = (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
517: else ierr = (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
519: ierr = PetscAttachDebugger();
520: (void)ierr;
521: abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
522: PetscFunctionReturn(PETSC_SUCCESS);
523: }
525: /*@C
526: PetscStopForDebugger - Prints a message to the screen indicating how to
527: attach to the process with the debugger and then waits for the
528: debugger to attach.
530: Not Collective
532: Options Database Key:
533: . -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
535: Level: developer
537: Note:
538: This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
540: Developer Notes:
541: Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
543: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
544: @*/
545: PetscErrorCode PetscStopForDebugger(void)
546: {
547: PetscErrorCode ierr;
548: PetscInt sleeptime = 0;
549: #if !defined(PETSC_CANNOT_START_DEBUGGER)
550: int ppid;
551: PetscMPIInt rank;
552: char program[PETSC_MAX_PATH_LEN], hostname[256];
553: PetscBool isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
554: #endif
556: PetscFunctionBegin;
557: #if defined(PETSC_CANNOT_START_DEBUGGER)
558: PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"));
559: #else
560: if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */
561: ierr = PetscGetHostName(hostname, sizeof(hostname));
562: if (ierr) {
563: PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"));
564: PetscFunctionReturn(PETSC_SUCCESS);
565: }
567: ierr = PetscGetProgramName(program, sizeof(program));
568: if (ierr) {
569: PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
570: PetscFunctionReturn(PETSC_SUCCESS);
571: }
572: if (!program[0]) {
573: PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
574: PetscFunctionReturn(PETSC_SUCCESS);
575: }
577: ppid = getpid();
579: PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
580: PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
581: PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
582: PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
583: PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
584: PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
585: PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
586: PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
588: if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
589: else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
590: else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
591: else if (isdbx) {
592: #if defined(PETSC_USE_P_FOR_DEBUGGER)
593: printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
594: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
595: printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
596: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
597: printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
598: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
599: printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
600: #else
601: printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
602: #endif
603: }
604: #endif /* PETSC_CANNOT_START_DEBUGGER */
606: fflush(stdout); /* ignore error because may already be in error handler */
608: sleeptime = 25; /* default to sleep waiting for debugger */
609: PetscCallContinue(PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); /* ignore error because may already be in error handler */
610: if (sleeptime < 0) sleeptime = -sleeptime;
611: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
612: /*
613: HP cannot attach process to sleeping debugger, hence count instead
614: */
615: {
616: // this *will* get optimized away by any compiler known to man
617: PetscReal x = 1.0;
618: int i = 10000000;
619: while (i--) x++; /* cannot attach to sleeper */
620: }
621: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
622: /*
623: IBM sleep may return at anytime, hence must see if there is more time to sleep
624: */
625: {
626: int left = sleeptime;
627: while (left > 0) left = sleep(left) - 1;
628: }
629: #else
630: PetscCall(PetscSleep(sleeptime));
631: #endif
632: PetscFunctionReturn(PETSC_SUCCESS);
633: }