1 /* 2 Code to handle PETSc starting up in debuggers,etc. 3 */ 4 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 Xterm = PETSC_TRUE; 17 18 #undef __FUNCT__ 19 #define __FUNCT__ "PetscSetDebugTerminal" 20 /*@C 21 PetscSetDebugTerminal - Sets the terminal to use (instead of xterm) for debugging. 22 23 Not Collective 24 25 Input Parameters: 26 + terminal - name of terminal and any flags required to execute a program. 27 For example "xterm -e", "urxvt -e". 28 29 Options Database Keys: 30 -debug_terminal terminal - use this terminal instead of xterm 31 32 Level: developer 33 34 Notes: 35 You can start the debugger for all processes in the same GNU screen session. 36 37 mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen" 38 39 will open 4 windows in the session named "debug". 40 41 Fortran Note: 42 This routine is not supported in Fortran. 43 44 Concepts: debugger^setting 45 46 .seealso: PetscSetDebugger() 47 @*/ 48 PetscErrorCode PetscSetDebugTerminal(const char terminal[]) 49 { 50 PetscErrorCode ierr; 51 52 PetscFunctionBegin; 53 ierr = PetscStrcpy(DebugTerminal,terminal);CHKERRQ(ierr); 54 PetscFunctionReturn(0); 55 } 56 57 #undef __FUNCT__ 58 #define __FUNCT__ "PetscSetDebugger" 59 /*@C 60 PetscSetDebugger - Sets options associated with the debugger. 61 62 Not Collective 63 64 Input Parameters: 65 + debugger - name of debugger, which should be in your path, 66 usually "lldb", "dbx", "gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX 67 supports "xdb", and IBM rs6000 supports "xldb". 68 69 - xterm - flag to indicate debugger window, set to either PETSC_TRUE (to indicate 70 debugger should be started in a new xterm) or PETSC_FALSE (to start debugger 71 in initial window (the option PETSC_FALSE makes no sense when using more 72 than one MPI process.) 73 74 Level: developer 75 76 Fortran Note: 77 This routine is not supported in Fortran. 78 79 Concepts: debugger^setting 80 81 .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler() 82 @*/ 83 PetscErrorCode PetscSetDebugger(const char debugger[],PetscBool xterm) 84 { 85 PetscErrorCode ierr; 86 87 PetscFunctionBegin; 88 if (debugger) { 89 ierr = PetscStrcpy(PetscDebugger,debugger);CHKERRQ(ierr); 90 } 91 Xterm = xterm; 92 PetscFunctionReturn(0); 93 } 94 95 #undef __FUNCT__ 96 #define __FUNCT__ "PetscSetDefaultDebugger" 97 /*@C 98 PetscSetDefaultDebugger - Causes PETSc to use its default debugger. 99 100 Not collective 101 102 Level: developer 103 104 .seealso: PetscSetDebugger(), PetscSetDebuggerFromString() 105 @*/ 106 PetscErrorCode PetscSetDefaultDebugger(void) 107 { 108 PetscErrorCode ierr; 109 110 PetscFunctionBegin; 111 #if defined(PETSC_USE_LLDB_DEBUGGER) 112 ierr = PetscSetDebugger("lldb",PETSC_TRUE);CHKERRQ(ierr); 113 #elif defined(PETSC_USE_DBX_DEBUGGER) 114 ierr = PetscSetDebugger("dbx",PETSC_TRUE);CHKERRQ(ierr); 115 #elif defined(PETSC_USE_XDB_DEBUGGER) 116 ierr = PetscSetDebugger("xdb",PETSC_TRUE);CHKERRQ(ierr); 117 #elif defined(PETSC_USE_IDB_DEBUGGER) 118 ierr = PetscSetDebugger("idb",PETSC_TRUE);CHKERRQ(ierr); 119 #else /* Default is gdb */ 120 ierr = PetscSetDebugger("gdb",PETSC_TRUE);CHKERRQ(ierr); 121 #endif 122 ierr = PetscSetDebugTerminal("xterm -e");CHKERRQ(ierr); 123 PetscFunctionReturn(0); 124 } 125 126 #undef __FUNCT__ 127 #define __FUNCT__ "PetscCheckDebugger_Private" 128 static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[]) 129 { 130 PetscBool exists; 131 char *f; 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 ierr = PetscStrstr(string, defaultDbg, &f);CHKERRQ(ierr); 136 if (f) { 137 ierr = PetscTestFile(string, 'x', &exists);CHKERRQ(ierr); 138 if (exists) *debugger = string; 139 else *debugger = defaultDbg; 140 } 141 PetscFunctionReturn(0); 142 } 143 144 #undef __FUNCT__ 145 #define __FUNCT__ "PetscSetDebuggerFromString" 146 /*@C 147 PetscSetDebuggerFromString - Set the complete path for the 148 debugger for PETSc to use. 149 150 Not collective 151 152 Level: developer 153 154 .seealso: PetscSetDebugger(), PetscSetDefaultDebugger() 155 @*/ 156 PetscErrorCode PetscSetDebuggerFromString(const char *string) 157 { 158 const char *debugger = NULL; 159 PetscBool xterm = PETSC_TRUE; 160 char *f; 161 PetscErrorCode ierr; 162 163 PetscFunctionBegin; 164 ierr = PetscStrstr(string, "noxterm", &f);CHKERRQ(ierr); 165 if (f) xterm = PETSC_FALSE; 166 ierr = PetscStrstr(string, "ddd", &f);CHKERRQ(ierr); 167 if (f) xterm = PETSC_FALSE; 168 ierr = PetscCheckDebugger_Private("xdb", string, &debugger);CHKERRQ(ierr); 169 ierr = PetscCheckDebugger_Private("dbx", string, &debugger);CHKERRQ(ierr); 170 ierr = PetscCheckDebugger_Private("xldb", string, &debugger);CHKERRQ(ierr); 171 ierr = PetscCheckDebugger_Private("gdb", string, &debugger);CHKERRQ(ierr); 172 ierr = PetscCheckDebugger_Private("idb", string, &debugger);CHKERRQ(ierr); 173 ierr = PetscCheckDebugger_Private("xxgdb", string, &debugger);CHKERRQ(ierr); 174 ierr = PetscCheckDebugger_Private("ddd", string, &debugger);CHKERRQ(ierr); 175 ierr = PetscCheckDebugger_Private("kdbg", string, &debugger);CHKERRQ(ierr); 176 ierr = PetscCheckDebugger_Private("ups", string, &debugger);CHKERRQ(ierr); 177 ierr = PetscCheckDebugger_Private("workshop", string, &debugger);CHKERRQ(ierr); 178 ierr = PetscCheckDebugger_Private("pgdbg", string, &debugger);CHKERRQ(ierr); 179 ierr = PetscCheckDebugger_Private("pathdb", string, &debugger);CHKERRQ(ierr); 180 ierr = PetscCheckDebugger_Private("lldb", string, &debugger);CHKERRQ(ierr); 181 182 ierr = PetscSetDebugger(debugger, xterm);CHKERRQ(ierr); 183 PetscFunctionReturn(0); 184 } 185 186 187 #undef __FUNCT__ 188 #define __FUNCT__ "PetscAttachDebugger" 189 /*@ 190 PetscAttachDebugger - Attaches the debugger to the running process. 191 192 Not Collective 193 194 Level: advanced 195 196 Concepts: debugger^starting from program 197 198 Developer Notes: Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()? 199 200 .seealso: PetscSetDebugger() 201 @*/ 202 PetscErrorCode PetscAttachDebugger(void) 203 { 204 #if !defined(PETSC_CANNOT_START_DEBUGGER) 205 int child =0; 206 PetscReal sleeptime=0; 207 PetscErrorCode ierr; 208 char program[PETSC_MAX_PATH_LEN],display[256],hostname[64]; 209 #endif 210 211 PetscFunctionBegin; 212 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 213 (*PetscErrorPrintf)("System cannot start debugger\n"); 214 (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 215 (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 216 MPI_Abort(PETSC_COMM_WORLD,1); 217 #else 218 ierr = PetscGetDisplay(display,128);CHKERRQ(ierr); 219 ierr = PetscGetProgramName(program,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 220 if (ierr) { 221 (*PetscErrorPrintf)("Cannot determine program name\n"); 222 PetscFunctionReturn(1); 223 } 224 if (!program[0]) { 225 (*PetscErrorPrintf)("Cannot determine program name\n"); 226 PetscFunctionReturn(1); 227 } 228 child = (int)fork(); 229 if (child < 0) { 230 (*PetscErrorPrintf)("Error in fork() attaching debugger\n"); 231 PetscFunctionReturn(1); 232 } 233 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 (child) child = 0; 239 else child = (int)getppid(); 240 241 if (child) { /* I am the parent, will run the debugger */ 242 const char *args[10]; 243 char pid[10]; 244 PetscInt j,jj; 245 PetscBool isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg,islldb; 246 247 ierr = PetscGetHostName(hostname,64);CHKERRQ(ierr); 248 /* 249 We need to send a continue signal to the "child" process on the 250 alpha, otherwise it just stays off forever 251 */ 252 #if defined(PETSC_NEED_KILL_FOR_DEBUGGER) 253 kill(child,SIGCONT); 254 #endif 255 sprintf(pid,"%d",child); 256 257 ierr = PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 258 ierr = PetscStrcmp(PetscDebugger,"ddd",&isddd);CHKERRQ(ierr); 259 ierr = PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);CHKERRQ(ierr); 260 ierr = PetscStrcmp(PetscDebugger,"ups",&isups);CHKERRQ(ierr); 261 ierr = PetscStrcmp(PetscDebugger,"xldb",&isxldb);CHKERRQ(ierr); 262 ierr = PetscStrcmp(PetscDebugger,"xdb",&isxdb);CHKERRQ(ierr); 263 ierr = PetscStrcmp(PetscDebugger,"dbx",&isdbx);CHKERRQ(ierr); 264 ierr = PetscStrcmp(PetscDebugger,"idb",&isidb);CHKERRQ(ierr); 265 ierr = PetscStrcmp(PetscDebugger,"workshop",&isworkshop);CHKERRQ(ierr); 266 ierr = PetscStrcmp(PetscDebugger,"lldb",&islldb);CHKERRQ(ierr); 267 268 if (isxxgdb || isups || isddd) { 269 args[1] = program; args[2] = pid; args[3] = "-display"; 270 args[0] = PetscDebugger; args[4] = display; args[5] = 0; 271 printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 272 if (execvp(args[0],(char**)args) < 0) { 273 perror("Unable to start debugger"); 274 exit(0); 275 } 276 } else if (iskdbg) { 277 args[1] = "-p"; args[2] = pid; args[3] = program; args[4] = "-display"; 278 args[0] = PetscDebugger; args[5] = display; args[6] = 0; 279 printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname); 280 if (execvp(args[0],(char**)args) < 0) { 281 perror("Unable to start debugger"); 282 exit(0); 283 } 284 } else if (isxldb) { 285 args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display"; 286 args[0] = PetscDebugger; args[5] = display; args[6] = 0; 287 printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 288 if (execvp(args[0],(char**)args) < 0) { 289 perror("Unable to start debugger"); 290 exit(0); 291 } 292 } else if (isworkshop) { 293 args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-"; 294 args[0] = PetscDebugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0; 295 printf("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname); 296 if (execvp(args[0],(char**)args) < 0) { 297 perror("Unable to start debugger"); 298 exit(0); 299 } 300 } else { 301 j = 0; 302 if (Xterm) { 303 PetscBool cmp; 304 char *tmp,*tmp1; 305 ierr = PetscStrncmp(DebugTerminal,"screen",6,&cmp);CHKERRQ(ierr); 306 if (cmp) display[0] = 0; /* when using screen, we never pass -display */ 307 args[j++] = tmp = DebugTerminal; 308 if (display[0]) { 309 args[j++] = "-display"; args[j++] = display; 310 } 311 while (*tmp) { 312 ierr = PetscStrchr(tmp,' ',&tmp1);CHKERRQ(ierr); 313 if (!tmp1) break; 314 *tmp1 = 0; 315 tmp = tmp1+1; 316 args[j++] = tmp; 317 } 318 } 319 args[j++] = PetscDebugger; 320 jj = j; 321 args[j++] = program; args[j++] = pid; args[j++] = 0; 322 323 if (isidb) { 324 j = jj; 325 args[j++] = "-pid"; 326 args[j++] = pid; 327 args[j++] = "-gdb"; 328 args[j++] = program; 329 args[j++] = 0; 330 } 331 if (islldb) { 332 j = jj; 333 args[j++] = "-p"; 334 args[j++] = pid; 335 args[j++] = 0; 336 } 337 if (isdbx) { 338 j = jj; 339 #if defined(PETSC_USE_P_FOR_DEBUGGER) 340 args[j++] = "-p"; 341 args[j++] = pid; 342 args[j++] = program; 343 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 344 args[j++] = "-l"; 345 args[j++] = "ALL"; 346 args[j++] = "-P"; 347 args[j++] = pid; 348 args[j++] = program; 349 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 350 args[j++] = "-a"; 351 args[j++] = pid; 352 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 353 args[j++] = "-pid"; 354 args[j++] = pid; 355 args[j++] = program; 356 #else 357 args[j++] = program; 358 args[j++] = pid; 359 #endif 360 args[j++] = 0; 361 } 362 if (Xterm) { 363 if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",PetscDebugger,program,pid,display,hostname); 364 else printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname); 365 366 if (execvp(args[0],(char**)args) < 0) { 367 perror("Unable to start debugger in xterm"); 368 exit(0); 369 } 370 } else { 371 printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname); 372 if (execvp(args[0],(char**)args) < 0) { 373 perror("Unable to start debugger"); 374 exit(0); 375 } 376 } 377 } 378 } else { /* I am the child, continue with user code */ 379 sleeptime = 10; /* default to sleep waiting for debugger */ 380 ierr = PetscOptionsGetReal(NULL,"-debugger_pause",&sleeptime,NULL);CHKERRQ(ierr); 381 if (sleeptime < 0) sleeptime = -sleeptime; 382 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 383 /* 384 HP cannot attach process to sleeping debugger, hence count instead 385 */ 386 { 387 PetscReal x = 1.0; 388 int i =10000000; 389 while (i--) x++; /* cannot attach to sleeper */ 390 } 391 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 392 /* 393 IBM sleep may return at anytime, hence must see if there is more time to sleep 394 */ 395 { 396 int left = sleeptime; 397 while (left > 0) left = PetscSleep(left) - 1; 398 } 399 #else 400 PetscSleep(sleeptime); 401 #endif 402 } 403 #endif 404 PetscFunctionReturn(0); 405 } 406 407 #undef __FUNCT__ 408 #define __FUNCT__ "PetscAttachDebuggerErrorHandler" 409 /*@C 410 PetscAttachDebuggerErrorHandler - Error handler that attaches 411 a debugger to a running process when an error is detected. 412 This routine is useful for examining variables, etc. 413 414 Not Collective 415 416 Input Parameters: 417 + comm - communicator over which error occurred 418 . line - the line number of the error (indicated by __LINE__) 419 . fun - function where error occured (indicated by __FUNCT__) 420 . file - the file in which the error was detected (indicated by __FILE__) 421 . message - an error text string, usually just printed to the screen 422 . number - the generic error number 423 . p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT 424 - ctx - error handler context 425 426 Options Database Keys: 427 . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates 428 debugger attachment 429 430 Level: developer 431 432 Notes: 433 By default the GNU debugger, gdb, is used. Alternatives are lldb, dbx and 434 xxgdb,xldb (on IBM rs6000), xdb (on HP-UX). 435 436 Most users need not directly employ this routine and the other error 437 handlers, but can instead use the simplified interface SETERR, which has 438 the calling sequence 439 $ SETERRQ(PETSC_COMM_SELF,number,p,message) 440 441 Notes for experienced users: 442 Use PetscPushErrorHandler() to set the desired error handler. The 443 currently available PETSc error handlers are 444 $ PetscTraceBackErrorHandler() 445 $ PetscAttachDebuggerErrorHandler() 446 $ PetscAbortErrorHandler() 447 or you may write your own. 448 449 Concepts: debugger^error handler 450 Concepts: error handler^attach debugger 451 452 .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 453 PetscAbortErrorHandler() 454 @*/ 455 PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx) 456 { 457 PetscErrorCode ierr; 458 459 PetscFunctionBegin; 460 if (!fun) fun = "User provided function"; 461 if (!mess) mess = " "; 462 463 (*PetscErrorPrintf)("%s() line %d in %s %s\n",fun,line,file,mess); 464 465 ierr = PetscAttachDebugger(); 466 if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */ 467 PetscFunctionReturn(0); 468 } 469 470 #undef __FUNCT__ 471 #define __FUNCT__ "PetscStopForDebugger" 472 /*@C 473 PetscStopForDebugger - Prints a message to the screen indicating how to 474 attach to the process with the debugger and then waits for the 475 debugger to attach. 476 477 Not Collective 478 479 Level: developer 480 481 Notes: This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work. 482 483 Developer Notes: Since this can be called by the error handler, should it be calling SETERRQ() and CHKERRQ()? 484 485 Concepts: debugger^waiting for attachment 486 487 .seealso: PetscSetDebugger(), PetscAttachDebugger() 488 @*/ 489 PetscErrorCode PetscStopForDebugger(void) 490 { 491 PetscErrorCode ierr; 492 PetscInt sleeptime=0; 493 #if !defined(PETSC_CANNOT_START_DEBUGGER) 494 int ppid; 495 PetscMPIInt rank; 496 char program[PETSC_MAX_PATH_LEN],hostname[256]; 497 PetscBool isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb; 498 #endif 499 500 PetscFunctionBegin; 501 #if defined(PETSC_CANNOT_START_DEBUGGER) 502 (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"); 503 #else 504 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); 505 if (ierr) rank = 0; /* ignore error since this may be already in error handler */ 506 ierr = PetscGetHostName(hostname,256); 507 if (ierr) { 508 (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"); 509 PetscFunctionReturn(0); 510 } 511 512 ierr = PetscGetProgramName(program,256); 513 if (ierr) { 514 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 515 PetscFunctionReturn(0); 516 } 517 if (!program[0]) { 518 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 519 PetscFunctionReturn(0); 520 } 521 522 ppid = getpid(); 523 524 ierr = PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 525 ierr = PetscStrcmp(PetscDebugger,"ddd",&isddd);CHKERRQ(ierr); 526 ierr = PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);CHKERRQ(ierr); 527 ierr = PetscStrcmp(PetscDebugger,"ups",&isups);CHKERRQ(ierr); 528 ierr = PetscStrcmp(PetscDebugger,"xldb",&isxldb);CHKERRQ(ierr); 529 ierr = PetscStrcmp(PetscDebugger,"xdb",&isxdb);CHKERRQ(ierr); 530 ierr = PetscStrcmp(PetscDebugger,"dbx",&isdbx);CHKERRQ(ierr); 531 ierr = PetscStrcmp(PetscDebugger,"lldb",&islldb);CHKERRQ(ierr); 532 533 if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid); 534 else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program); 535 else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid); 536 else if (isdbx) { 537 #if defined(PETSC_USE_P_FOR_DEBUGGER) 538 printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program); 539 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 540 printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program); 541 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 542 printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid); 543 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 544 printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program); 545 #else 546 printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid); 547 #endif 548 } 549 #endif /* PETSC_CANNOT_START_DEBUGGER */ 550 551 fflush(stdout); /* ignore error because may already be in error handler */ 552 553 sleeptime = 25; /* default to sleep waiting for debugger */ 554 PetscOptionsGetInt(NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */ 555 if (sleeptime < 0) sleeptime = -sleeptime; 556 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 557 /* 558 HP cannot attach process to sleeping debugger, hence count instead 559 */ 560 { 561 PetscReal x = 1.0; 562 int i =10000000; 563 while (i--) x++; /* cannot attach to sleeper */ 564 } 565 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 566 /* 567 IBM sleep may return at anytime, hence must see if there is more time to sleep 568 */ 569 { 570 int left = sleeptime; 571 while (left > 0) left = sleep(left) - 1; 572 } 573 #else 574 PetscSleep(sleeptime); 575 #endif 576 PetscFunctionReturn(0); 577 } 578 579 580 581