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> /*I "petscsys.h" I*/
6 #include <signal.h>
7 #if defined(PETSC_HAVE_UNISTD_H)
8 #include <unistd.h>
9 #endif
10
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;
19
20 /*@
21 PetscSetDebugTerminal - Sets the terminal to use for debugging.
22
23 Not Collective; No Fortran Support
24
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)
29
30 Options Database Key:
31 . -debug_terminal terminal - use this terminal instead of the default
32
33 Level: developer
34
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
40
41 will open 4 windows in the session named "debug".
42
43 The default terminal on Apple is Terminal, on other systems the default is xterm
44
45 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
46 @*/
PetscSetDebugTerminal(const char terminal[])47 PetscErrorCode PetscSetDebugTerminal(const char terminal[])
48 {
49 PetscBool xterm;
50
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 }
57
58 /*@
59 PetscSetDebugger - Sets options associated with the debugger.
60
61 Not Collective; No Fortran Support
62
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".
67
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.)
72
73 Level: developer
74
75 .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
76 @*/
PetscSetDebugger(const char debugger[],PetscBool usedebugterminal)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 }
84
85 /*@
86 PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal
87
88 Not Collective, No Fortran Support
89
90 Level: developer
91
92 .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()`
93 @*/
PetscSetDefaultDebugger(void)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 }
107
PetscCheckDebugger_Private(const char defaultDbg[],const char string[],const char * debugger[])108 static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
109 {
110 char *f = NULL;
111
112 PetscFunctionBegin;
113 PetscCall(PetscStrstr(string, defaultDbg, &f));
114 if (f) {
115 PetscBool exists;
116
117 PetscCall(PetscTestFile(string, 'x', &exists));
118 if (exists) *debugger = string;
119 else *debugger = defaultDbg;
120 }
121 PetscFunctionReturn(PETSC_SUCCESS);
122 }
123
124 /*@
125 PetscSetDebuggerFromString - Set the complete path for the
126 debugger for PETSc to use.
127
128 Not Collective
129
130 Input Parameter:
131 . string - the name of the debugger, for example "gdb"
132
133 Level: developer
134
135 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscAttachDebugger()`
136 @*/
PetscSetDebuggerFromString(const char string[])137 PetscErrorCode PetscSetDebuggerFromString(const char string[])
138 {
139 const char *debugger = NULL;
140 PetscBool useterminal = PETSC_TRUE;
141 char *f = NULL;
142
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 }
167
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.
171
172 Not Collective
173
174 Level: advanced
175
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.
179
180 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
181 @*/
PetscWaitOnError(void)182 PetscErrorCode PetscWaitOnError(void)
183 {
184 petscwaitonerrorflg = PETSC_TRUE;
185 return PETSC_SUCCESS;
186 }
187
188 /*@
189 PetscAttachDebugger - Attaches the debugger to the running process.
190
191 Not Collective
192
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.
200
201 Level: advanced
202
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`
207
208 Developer Note:
209 Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
210
211 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
212 @*/
PetscAttachDebugger(void)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
221
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;
247
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
255
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;
261
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));
271
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));
282
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 }
357
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;
380
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);
423
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 }
464
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.
469
470 Not Collective, No Fortran Support
471
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
481
482 Level: developer
483
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).
487
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
494
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.
503
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.
507
508 .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
509 `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
510 @*/
PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char * fun,const char * file,PetscErrorCode num,PetscErrorType p,const char * mess,PetscCtx ctx)511 PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, PetscCtx ctx)
512 {
513 (void)comm;
514 (void)num;
515 (void)p;
516 (void)ctx;
517 if (!mess) mess = " ";
518
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);
521
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 }
526
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.
531
532 Not Collective, No Fortran Support
533
534 Options Database Key:
535 . -stop_for_debugger - will stop for you to attach the debugger when `PetscInitialize()` is called
536
537 Level: developer
538
539 Note:
540 This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
541
542 Developer Note:
543 Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
544
545 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
546 @*/
PetscStopForDebugger(void)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
557
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 }
568
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 }
578
579 ppid = getpid();
580
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));
589
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 */
607
608 fflush(stdout); /* ignore error because may already be in error handler */
609
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 }
636