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 ierr = PetscCheckDebugger_Private("pathdb", string, &debugger);CHKERRQ(ierr); 147 148 ierr = PetscSetDebugger(debugger, xterm);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 153 #undef __FUNCT__ 154 #define __FUNCT__ "PetscAttachDebugger" 155 /*@ 156 PetscAttachDebugger - Attaches the debugger to the running process. 157 158 Not Collective 159 160 Level: advanced 161 162 Concepts: debugger^starting from program 163 164 .seealso: PetscSetDebugger() 165 @*/ 166 PetscErrorCode PETSC_DLLEXPORT PetscAttachDebugger(void) 167 { 168 #if !defined(PETSC_CANNOT_START_DEBUGGER) 169 int child=0; 170 PetscInt sleeptime=0; 171 PetscErrorCode ierr; 172 char program[PETSC_MAX_PATH_LEN],display[256],hostname[64]; 173 #endif 174 175 PetscFunctionBegin; 176 177 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 178 (*PetscErrorPrintf)("System cannot start debugger\n"); 179 (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 180 (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 181 MPI_Finalize(); 182 exit(0); 183 #else 184 ierr = PetscGetDisplay(display,128);CHKERRQ(ierr); 185 ierr = PetscGetProgramName(program,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 186 if (ierr) { 187 (*PetscErrorPrintf)("Cannot determine program name\n"); 188 PetscFunctionReturn(1); 189 } 190 if (!program[0]) { 191 (*PetscErrorPrintf)("Cannot determine program name\n"); 192 PetscFunctionReturn(1); 193 } 194 child = (int)fork(); 195 if (child < 0) { 196 (*PetscErrorPrintf)("Error in fork() attaching debugger\n"); 197 PetscFunctionReturn(1); 198 } 199 200 /* 201 Swap role the parent and child. This is (I think) so that control c typed 202 in the debugger goes to the correct process. 203 */ 204 if (child) { child = 0; } 205 else { child = (int)getppid(); } 206 207 if (child) { /* I am the parent, will run the debugger */ 208 const char *args[10]; 209 char pid[10]; 210 PetscTruth isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd; 211 212 ierr = PetscGetHostName(hostname,64);CHKERRQ(ierr); 213 /* 214 We need to send a continue signal to the "child" process on the 215 alpha, otherwise it just stays off forever 216 */ 217 #if defined (PETSC_NEED_KILL_FOR_DEBUGGER) 218 kill(child,SIGCONT); 219 #endif 220 sprintf(pid,"%d",child); 221 222 ierr = PetscStrcmp(Debugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 223 ierr = PetscStrcmp(Debugger,"ddd",&isddd);CHKERRQ(ierr); 224 ierr = PetscStrcmp(Debugger,"ups",&isups);CHKERRQ(ierr); 225 ierr = PetscStrcmp(Debugger,"xldb",&isxldb);CHKERRQ(ierr); 226 ierr = PetscStrcmp(Debugger,"xdb",&isxdb);CHKERRQ(ierr); 227 ierr = PetscStrcmp(Debugger,"dbx",&isdbx);CHKERRQ(ierr); 228 ierr = PetscStrcmp(Debugger,"idb",&isidb);CHKERRQ(ierr); 229 ierr = PetscStrcmp(Debugger,"workshop",&isworkshop);CHKERRQ(ierr); 230 231 if (isxxgdb || isups || isddd) { 232 args[1] = program; args[2] = pid; args[3] = "-display"; 233 args[0] = Debugger; args[4] = display; args[5] = 0; 234 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 235 if (execvp(args[0],(char**)args) < 0) { 236 perror("Unable to start debugger"); 237 exit(0); 238 } 239 } else if (isxldb) { 240 args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display"; 241 args[0] = Debugger; args[5] = display; args[6] = 0; 242 (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname); 243 if (execvp(args[0],(char**)args) < 0) { 244 perror("Unable to start debugger"); 245 exit(0); 246 } 247 } else if (isworkshop) { 248 args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-"; 249 args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0; 250 (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname); 251 if (execvp(args[0],(char**)args) < 0) { 252 perror("Unable to start debugger"); 253 exit(0); 254 } 255 } else if (!Xterm) { 256 args[1] = program; args[2] = pid; args[3] = 0; 257 args[0] = Debugger; 258 if (isidb) { 259 args[1] = "-pid"; 260 args[2] = pid; 261 args[3] = "-gdb"; 262 args[4] = program; 263 args[5] = 0; 264 } 265 #if defined(PETSC_USE_P_FOR_DEBUGGER) 266 if (isdbx) { 267 args[1] = "-p"; 268 args[2] = pid; 269 args[3] = program; 270 args[4] = 0; 271 } 272 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 273 if (isxdb) { 274 args[1] = "-l"; 275 args[2] = "ALL"; 276 args[3] = "-P"; 277 args[4] = pid; 278 args[5] = program; 279 args[6] = 0; 280 } 281 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 282 if (isdbx) { 283 args[1] = "-a"; 284 args[2] = pid; 285 args[3] = 0; 286 } 287 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 288 if (isdbx) { 289 args[1] = "-pid"; 290 args[2] = pid; 291 args[3] = program; 292 args[4] = 0; 293 } 294 #endif 295 (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %s\n",Debugger,program,pid,hostname); 296 if (execvp(args[0],(char**)args) < 0) { 297 perror("Unable to start debugger"); 298 exit(0); 299 } 300 } else { 301 if (!display[0]) { 302 args[0] = "xterm"; args[1] = "-e"; 303 args[2] = Debugger; args[3] = program; 304 args[4] = pid; args[5] = 0; 305 if (isidb) { 306 args[3] = "-pid"; 307 args[4] = pid; 308 args[5] = "-gdb"; 309 args[6] = program; 310 args[7] = 0; 311 } 312 #if defined(PETSC_USE_P_FOR_DEBUGGER) 313 if (isdbx) { 314 args[3] = "-p"; 315 args[4] = pid; 316 args[5] = program; 317 args[6] = 0; 318 } 319 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 320 if (isxdb) { 321 args[5] = program; 322 args[3] = "-P"; 323 args[4] = pid; 324 args[6] = 0; 325 } 326 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 327 if (isdbx) { 328 args[3] = "-a"; 329 args[4] = pid; 330 args[5] = 0; 331 } 332 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 333 if (isdbx) { 334 args[3] = "-pid"; 335 args[4] = pid; 336 args[5] = program; 337 args[6] = 0; 338 } 339 #endif 340 (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %s\n",Debugger,program,pid,hostname); 341 } else { 342 args[0] = "xterm"; args[1] = "-display"; 343 args[2] = display; args[3] = "-e"; 344 args[4] = Debugger; args[5] = program; 345 args[6] = pid; args[7] = 0; 346 if (isidb) { 347 args[5] = "-pid"; 348 args[6] = pid; 349 args[7] = "-gdb"; 350 args[8] = program; 351 args[9] = 0; 352 } 353 #if defined(PETSC_USE_P_FOR_DEBUGGER) 354 if (isdbx) { 355 args[5] = "-p"; 356 args[6] = pid; 357 args[7] = program; 358 args[8] = 0; 359 } 360 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 361 if (isxdb) { 362 args[7] = program; 363 args[5] = "-P"; 364 args[6] = pid; 365 args[8] = 0; 366 } 367 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 368 if (isdbx) { 369 args[5] = "-a"; 370 args[6] = pid; 371 args[7] = 0; 372 } 373 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 374 if (isdbx) { 375 args[5] = "-pid"; 376 args[6] = pid; 377 args[7] = program; 378 args[8] = 0; 379 } 380 #endif 381 (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",Debugger,program,pid,display,hostname); 382 } 383 384 if (execvp("xterm",(char**)args) < 0) { 385 perror("Unable to start debugger in xterm"); 386 exit(0); 387 } 388 } 389 } else { /* I am the child, continue with user code */ 390 sleeptime = 10; /* default to sleep waiting for debugger */ 391 ierr = PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);CHKERRQ(ierr); 392 if (sleeptime < 0) sleeptime = -sleeptime; 393 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 394 /* 395 HP cannot attach process to sleeping debugger, hence count instead 396 */ 397 { 398 PetscReal x = 1.0; 399 int i=10000000; 400 while (i--) x++ ; /* cannot attach to sleeper */ 401 } 402 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 403 /* 404 IBM sleep may return at anytime, hence must see if there is more time to sleep 405 */ 406 { 407 int left = sleeptime; 408 while (left > 0) {left = PetscSleep(left) - 1;} 409 } 410 #else 411 PetscSleep(sleeptime); 412 #endif 413 } 414 #endif 415 PetscFunctionReturn(0); 416 } 417 418 #undef __FUNCT__ 419 #define __FUNCT__ "PetscAttachDebuggerErrorHandler" 420 /*@C 421 PetscAttachDebuggerErrorHandler - Error handler that attaches 422 a debugger to a running process when an error is detected. 423 This routine is useful for examining variables, etc. 424 425 Not Collective 426 427 Input Parameters: 428 + line - the line number of the error (indicated by __LINE__) 429 . fun - function where error occured (indicated by __FUNCT__) 430 . file - the file in which the error was detected (indicated by __FILE__) 431 . dir - the directory of the file (indicated by __SDIR__) 432 . message - an error text string, usually just printed to the screen 433 . number - the generic error number 434 . p - the specific error number 435 - ctx - error handler context 436 437 Options Database Keys: 438 . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates 439 debugger attachment 440 441 Level: developer 442 443 Notes: 444 By default the GNU debugger, gdb, is used. Alternatives are dbx and 445 xxgdb,xldb (on IBM rs6000), xdb (on HP-UX). 446 447 Most users need not directly employ this routine and the other error 448 handlers, but can instead use the simplified interface SETERR, which has 449 the calling sequence 450 $ SETERRQ(number,p,message) 451 452 Notes for experienced users: 453 Use PetscPushErrorHandler() to set the desired error handler. The 454 currently available PETSc error handlers are 455 $ PetscTraceBackErrorHandler() 456 $ PetscAttachDebuggerErrorHandler() 457 $ PetscAbortErrorHandler() 458 or you may write your own. 459 460 Concepts: debugger^error handler 461 Concepts: error handler^attach debugger 462 463 .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(), 464 PetscAbortErrorHandler() 465 @*/ 466 PetscErrorCode PETSC_DLLEXPORT PetscAttachDebuggerErrorHandler(int line,const char* fun,const char *file,const char* dir,int num,int p,const char* mess,void *ctx) 467 { 468 PetscErrorCode ierr; 469 470 PetscFunctionBegin; 471 if (!fun) fun = "User provided function"; 472 if (!dir) dir = " "; 473 if (!mess) mess = " "; 474 475 (*PetscErrorPrintf)("%s() line %d in %s%s %s\n",fun,line,dir,file,mess); 476 477 ierr = PetscAttachDebugger(); 478 if (ierr) { /* hopeless so get out */ 479 MPI_Finalize(); 480 exit(num); 481 } 482 PetscFunctionReturn(0); 483 } 484 485 #undef __FUNCT__ 486 #define __FUNCT__ "PetscStopForDebugger" 487 /*@C 488 PetscStopForDebugger - Prints a message to the screen indicating how to 489 attach to the process with the debugger and then waits for the 490 debugger to attach. 491 492 Not Collective 493 494 Level: advanced 495 496 Concepts: debugger^waiting for attachment 497 498 .seealso: PetscSetDebugger(), PetscAttachDebugger() 499 @*/ 500 PetscErrorCode PETSC_DLLEXPORT PetscStopForDebugger(void) 501 { 502 PetscErrorCode ierr; 503 PetscInt sleeptime=0; 504 int err; 505 #if !defined(PETSC_CANNOT_START_DEBUGGER) 506 int ppid; 507 PetscMPIInt rank; 508 char program[PETSC_MAX_PATH_LEN],hostname[256]; 509 PetscTruth isdbx,isxldb,isxxgdb,isddd,isups,isxdb; 510 #endif 511 512 PetscFunctionBegin; 513 #if defined(PETSC_CANNOT_START_DEBUGGER) 514 (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"); 515 #else 516 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); 517 ierr = PetscGetHostName(hostname,256); 518 if (ierr) { 519 (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"); 520 PetscFunctionReturn(0); 521 } 522 523 ierr = PetscGetProgramName(program,256); 524 if (ierr) { 525 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 526 PetscFunctionReturn(0); 527 } 528 if (!program[0]) { 529 (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"); 530 PetscFunctionReturn(0); 531 } 532 533 ppid = getpid(); 534 535 ierr = PetscStrcmp(Debugger,"xxgdb",&isxxgdb);CHKERRQ(ierr); 536 ierr = PetscStrcmp(Debugger,"ddd",&isddd);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 ) { 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