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