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