1 #define PETSC_DLL 2 /* 3 Code to handle PETSc starting up in debuggers,etc. 4 */ 5 6 #include "petsc.h" /*I "petsc.h" I*/ 7 #include <signal.h> 8 #include "petscsys.h" /*I "petscsys.h" I*/ 9 #if defined(PETSC_HAVE_UNISTD_H) 10 #include <unistd.h> 11 #endif 12 #if defined(PETSC_HAVE_STDLIB_H) 13 #include <stdlib.h> 14 #endif 15 #include "petscfix.h" 16 17 /* 18 These are the debugger and display used if the debugger is started up 19 */ 20 static char Debugger[PETSC_MAX_PATH_LEN]; 21 static PetscTruth Xterm = PETSC_TRUE; 22 23 #undef __FUNCT__ 24 #define __FUNCT__ "PetscSetDebugger" 25 /*@C 26 PetscSetDebugger - Sets options associated with the debugger. 27 28 Not Collective 29 30 Input Parameters: 31 + debugger - name of debugger, which should be in your path, 32 usually "dbx", "gdb", "idb", "xxgdb" or "ddd". Also, HP-UX 33 supports "xdb", and IBM rs6000 supports "xldb". 34 35 - xterm - flag to indicate debugger window, set to either 1 (to indicate 36 debugger should be started in a new xterm) or 0 (to start debugger 37 in initial window (the option 0 makes no sense when using more 38 than one processor.) 39 40 Level: developer 41 42 Fortran Note: 43 This routine is not supported in Fortran. 44 45 Concepts: debugger^setting 46 47 .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler() 48 @*/ 49 PetscErrorCode PETSC_DLLEXPORT PetscSetDebugger(const char debugger[],PetscTruth xterm) 50 { 51 PetscErrorCode ierr; 52 53 PetscFunctionBegin; 54 if (debugger) { 55 ierr = PetscStrcpy(Debugger,debugger);CHKERRQ(ierr); 56 } 57 Xterm = xterm; 58 59 PetscFunctionReturn(0); 60 } 61 62 #undef __FUNCT__ 63 #define __FUNCT__ "PetscSetDefaultDebugger" 64 /*@ 65 PetscSetDefaultDebugger - Causes PETSc to use its default 66 debugger. 67 68 Not collective 69 70 Level: advanced 71 72 .seealso: PetscSetDebugger(), PetscSetDebuggerFromString() 73 @*/ 74 PetscErrorCode PETSC_DLLEXPORT PetscSetDefaultDebugger(void) 75 { 76 PetscErrorCode ierr; 77 78 PetscFunctionBegin; 79 #if defined(PETSC_USE_DBX_DEBUGGER) 80 ierr = PetscSetDebugger("dbx",PETSC_TRUE);CHKERRQ(ierr); 81 #elif defined(PETSC_USE_XDB_DEBUGGER) 82 ierr = PetscSetDebugger("xdb",PETSC_TRUE);CHKERRQ(ierr); 83 #elif defined(PETSC_USE_IDB_DEBUGGER) 84 ierr = PetscSetDebugger("idb",PETSC_TRUE);CHKERRQ(ierr); 85 #else /* Default is gdb */ 86 ierr = PetscSetDebugger("gdb",PETSC_TRUE);CHKERRQ(ierr); 87 #endif 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "PetscCheckDebugger_Private" 93 static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[]) 94 { 95 PetscTruth exists; 96 char *f; 97 PetscErrorCode ierr; 98 99 PetscFunctionBegin; 100 ierr = PetscStrstr(string, defaultDbg, &f);CHKERRQ(ierr); 101 if (f) { 102 ierr = PetscTestFile(string, 'x', &exists);CHKERRQ(ierr); 103 if (exists) { 104 *debugger = string; 105 } else { 106 *debugger = defaultDbg; 107 } 108 } 109 PetscFunctionReturn(0); 110 } 111 112 #undef __FUNCT__ 113 #define __FUNCT__ "PetscSetDebuggerFromString" 114 /*@C 115 PetscSetDebuggerFromString - Set the complete path for the 116 debugger for PETSc to use. 117 118 Not collective 119 120 Level: advanced 121 122 .seealso: PetscSetDebugger(), PetscSetDefaultDebugger() 123 @*/ 124 PetscErrorCode PETSC_DLLEXPORT PetscSetDebuggerFromString(char *string) 125 { 126 const char *debugger = PETSC_NULL; 127 PetscTruth xterm = PETSC_TRUE; 128 char *f; 129 PetscErrorCode ierr; 130 131 PetscFunctionBegin; 132 ierr = PetscStrstr(string, "noxterm", &f);CHKERRQ(ierr); 133 if (f) xterm = PETSC_FALSE; 134 ierr = PetscStrstr(string, "ddd", &f);CHKERRQ(ierr); 135 if (f) xterm = PETSC_FALSE; 136 ierr = PetscCheckDebugger_Private("xdb", string, &debugger);CHKERRQ(ierr); 137 ierr = PetscCheckDebugger_Private("dbx", string, &debugger);CHKERRQ(ierr); 138 ierr = PetscCheckDebugger_Private("xldb", string, &debugger);CHKERRQ(ierr); 139 ierr = PetscCheckDebugger_Private("gdb", string, &debugger);CHKERRQ(ierr); 140 ierr = PetscCheckDebugger_Private("idb", string, &debugger);CHKERRQ(ierr); 141 ierr = PetscCheckDebugger_Private("xxgdb", string, &debugger);CHKERRQ(ierr); 142 ierr = PetscCheckDebugger_Private("ddd", string, &debugger);CHKERRQ(ierr); 143 ierr = PetscCheckDebugger_Private("ups", string, &debugger);CHKERRQ(ierr); 144 ierr = PetscCheckDebugger_Private("workshop", string, &debugger);CHKERRQ(ierr); 145 ierr = PetscCheckDebugger_Private("pgdbg", string, &debugger);CHKERRQ(ierr); 146 147 ierr = PetscSetDebugger(debugger, xterm);CHKERRQ(ierr); 148 PetscFunctionReturn(0); 149 } 150 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "PetscAttachDebugger" 154 /*@ 155 PetscAttachDebugger - Attaches the debugger to the running process. 156 157 Not Collective 158 159 Level: advanced 160 161 Concepts: debugger^starting from program 162 163 .seealso: PetscSetDebugger() 164 @*/ 165 PetscErrorCode PETSC_DLLEXPORT PetscAttachDebugger(void) 166 { 167 #if !defined(PETSC_CANNOT_START_DEBUGGER) 168 int child=0; 169 PetscInt sleeptime=0; 170 PetscErrorCode ierr; 171 char program[PETSC_MAX_PATH_LEN],display[256],hostname[64]; 172 #endif 173 174 PetscFunctionBegin; 175 176 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 177 (*PetscErrorPrintf)("System cannot start debugger\n"); 178 (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 179 (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 180 MPI_Finalize(); 181 exit(0); 182 #else 183 ierr = PetscGetDisplay(display,128);CHKERRQ(ierr); 184 ierr = PetscGetProgramName(program,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 185 if (ierr) { 186 (*PetscErrorPrintf)("Cannot determine program name\n"); 187 PetscFunctionReturn(1); 188 } 189 if (!program[0]) { 190 (*PetscErrorPrintf)("Cannot determine program name\n"); 191 PetscFunctionReturn(1); 192 } 193 child = (int)fork(); 194 if (child < 0) { 195 (*PetscErrorPrintf)("Error in fork() attaching debugger\n"); 196 PetscFunctionReturn(1); 197 } 198 199 /* 200 Swap role the parent and child. This is (I think) so that control c typed 201 in the debugger goes to the correct process. 202 */ 203 if (child) { child = 0; } 204 else { child = (int)getppid(); } 205 206 if (child) { /* I am the parent, will run the debugger */ 207 const char *args[10]; 208 char pid[10]; 209 PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd; 210 211 ierr = PetscGetHostName(hostname,64);CHKERRQ(ierr); 212 /* 213 We need to send a continue signal to the "child" process on the 214 alpha, otherwise it just stays off forever 215 */ 216 #if defined (PETSC_NEED_KILL_FOR_DEBUGGER) 217 kill(child,SIGCONT); 218 #endif 219 sprintf(pid,"%d",child); 220 221 ierr = PetscStrcmp(Debugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 222 ierr = PetscStrcmp(Debugger,"ddd",&isddd);CHKERRQ(ierr); 223 ierr = PetscStrcmp(Debugger,"ups",&isups);CHKERRQ(ierr); 224 ierr = PetscStrcmp(Debugger,"xldb",&isxldb);CHKERRQ(ierr); 225 ierr = PetscStrcmp(Debugger,"xdb",&isxdb);CHKERRQ(ierr); 226 ierr = PetscStrcmp(Debugger,"dbx",&isdbx);CHKERRQ(ierr); 227 ierr = PetscStrcmp(Debugger,"idb",&isidb);CHKERRQ(ierr); 228 ierr = PetscStrcmp(Debugger,"workshop",&isworkshop);CHKERRQ(ierr); 229 230 if (isxxgdb || isups || isddd) { 231 args[1] = program; args[2] = pid; args[3] = "-display"; 232 args[0] = Debugger; args[4] = display; args[5] = 0; 233 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 234 if (execvp(args[0],(char**)args) < 0) { 235 perror("Unable to start debugger"); 236 exit(0); 237 } 238 } else if (isxldb) { 239 args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display"; 240 args[0] = Debugger; args[5] = display; args[6] = 0; 241 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 242 if (execvp(args[0],(char**)args) < 0) { 243 perror("Unable to start debugger"); 244 exit(0); 245 } 246 } else if (isworkshop) { 247 args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-"; 248 args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0; 249 (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname); 250 if (execvp(args[0],(char**)args) < 0) { 251 perror("Unable to start debugger"); 252 exit(0); 253 } 254 } else if (!Xterm) { 255 args[1] = program; args[2] = pid; args[3] = 0; 256 args[0] = Debugger; 257 if (isidb) { 258 args[1] = "-pid"; 259 args[2] = pid; 260 args[3] = "-gdb"; 261 args[4] = program; 262 args[5] = 0; 263 } 264 #if defined(PETSC_USE_P_FOR_DEBUGGER) 265 if (isdbx) { 266 args[1] = "-p"; 267 args[2] = pid; 268 args[3] = program; 269 args[4] = 0; 270 } 271 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 272 if (isxdb) { 273 args[1] = "-l"; 274 args[2] = "ALL"; 275 args[3] = "-P"; 276 args[4] = pid; 277 args[5] = program; 278 args[6] = 0; 279 } 280 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 281 if (isdbx) { 282 args[1] = "-a"; 283 args[2] = pid; 284 args[3] = 0; 285 } 286 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 287 if (isdbx) { 288 args[1] = "-pid"; 289 args[2] = pid; 290 args[3] = program; 291 args[4] = 0; 292 } 293 #endif 294 (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname); 295 if (execvp(args[0],(char**)args) < 0) { 296 perror("Unable to start debugger"); 297 exit(0); 298 } 299 } else { 300 if (!display[0]) { 301 args[0] = "xterm"; args[1] = "-e"; 302 args[2] = Debugger; args[3] = program; 303 args[4] = pid; args[5] = 0; 304 if (isidb) { 305 args[3] = "-gdb"; 306 args[4] = pid; 307 args[5] = "-gdb"; 308 args[6] = program; 309 args[7] = 0; 310 } 311 #if defined(PETSC_USE_P_FOR_DEBUGGER) 312 if (isdbx) { 313 args[3] = "-p"; 314 args[4] = pid; 315 args[5] = program; 316 args[6] = 0; 317 } 318 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 319 if (isxdb) { 320 args[5] = program; 321 args[3] = "-P"; 322 args[4] = pid; 323 args[6] = 0; 324 } 325 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 326 if (isdbx) { 327 args[3] = "-a"; 328 args[4] = pid; 329 args[5] = 0; 330 } 331 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 332 if (isdbx) { 333 args[3] = "-pid"; 334 args[4] = pid; 335 args[5] = program; 336 args[6] = 0; 337 } 338 #endif 339 (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname); 340 } else { 341 args[0] = "xterm"; args[1] = "-display"; 342 args[2] = display; args[3] = "-e"; 343 args[4] = Debugger; args[5] = program; 344 args[6] = pid; args[7] = 0; 345 if (isidb) { 346 args[5] = "-pid"; 347 args[6] = pid; 348 args[7] = "-gdb"; 349 args[8] = program; 350 args[9] = 0; 351 } 352 #if defined(PETSC_USE_P_FOR_DEBUGGER) 353 if (isdbx) { 354 args[5] = "-p"; 355 args[6] = pid; 356 args[7] = program; 357 args[8] = 0; 358 } 359 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 360 if (isxdb) { 361 args[7] = program; 362 args[5] = "-P"; 363 args[6] = pid; 364 args[8] = 0; 365 } 366 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 367 if (isdbx) { 368 args[5] = "-a"; 369 args[6] = pid; 370 args[7] = 0; 371 } 372 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 373 if (isdbx) { 374 args[5] = "-pid"; 375 args[6] = pid; 376 args[7] = program; 377 args[8] = 0; 378 } 379 #endif 380 (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname); 381 } 382 383 if (execvp("xterm",(char**)args) < 0) { 384 perror("Unable to start debugger in xterm"); 385 exit(0); 386 } 387 } 388 } else { /* I am the child, continue with user code */ 389 sleeptime = 10; /* default to sleep waiting for debugger */ 390 ierr = PetscOptionsGetInt(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 #if !defined(PETSC_CANNOT_START_DEBUGGER) 504 int ppid; 505 PetscMPIInt rank; 506 char program[PETSC_MAX_PATH_LEN],hostname[256]; 507 PetscTruth isdbx,isxldb,isxxgdb,isddd,isups,isxdb; 508 #endif 509 510 PetscFunctionBegin; 511 #if defined(PETSC_CANNOT_START_DEBUGGER) 512 (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"); 513 #else 514 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); 515 ierr = PetscGetHostName(hostname,256); 516 if (ierr) { 517 (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"); 518 PetscFunctionReturn(0); 519 } 520 521 ierr = PetscGetProgramName(program,256); 522 if (ierr) { 523 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 524 PetscFunctionReturn(0); 525 } 526 if (!program[0]) { 527 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 528 PetscFunctionReturn(0); 529 } 530 531 ppid = getpid(); 532 533 ierr = PetscStrcmp(Debugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 534 ierr = PetscStrcmp(Debugger,"ddd",&isddd);CHKERRQ(ierr); 535 ierr = PetscStrcmp(Debugger,"ups",&isups);CHKERRQ(ierr); 536 ierr = PetscStrcmp(Debugger,"xldb",&isxldb);CHKERRQ(ierr); 537 ierr = PetscStrcmp(Debugger,"xdb",&isxdb);CHKERRQ(ierr); 538 ierr = PetscStrcmp(Debugger,"dbx",&isdbx);CHKERRQ(ierr); 539 540 if (isxxgdb || isups || isddd ) { 541 (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid); 542 } 543 #if defined(PETSC_USE_A_FOR_DEBUGGER) 544 else if (isxldb) { 545 (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program); 546 } 547 #endif 548 #if defined(PETSC_USE_P_FOR_DEBUGGER) 549 else if (isdbx) { 550 (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program); 551 } 552 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 553 else if (isxdb) { 554 (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program); 555 } 556 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 557 else if (isdbx) { 558 (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid); 559 } 560 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 561 else if (isdbx) { 562 (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program); 563 } 564 #else 565 else { 566 (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid); 567 } 568 #endif 569 #endif /* PETSC_CANNOT_START_DEBUGGER */ 570 571 fflush(stdout); 572 573 sleeptime = 25; /* default to sleep waiting for debugger */ 574 ierr = PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);CHKERRQ(ierr); 575 if (sleeptime < 0) sleeptime = -sleeptime; 576 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 577 /* 578 HP cannot attach process to sleeping debugger, hence count instead 579 */ 580 { 581 PetscReal x = 1.0; 582 int i=10000000; 583 while (i--) x++ ; /* cannot attach to sleeper */ 584 } 585 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 586 /* 587 IBM sleep may return at anytime, hence must see if there is more time to sleep 588 */ 589 { 590 int left = sleeptime; 591 while (left > 0) {left = sleep(left) - 1;} 592 } 593 #else 594 PetscSleep(sleeptime); 595 #endif 596 PetscFunctionReturn(0); 597 } 598 599 600 601