Actual source code: adebug.c
1: /*$Id: adebug.c,v 1.113 2001/03/23 23:20:26 balay Exp $*/
2: /*
3: Code to handle PETSc starting up in debuggers,etc.
4: */
6: #include petsc.h
7: #include <signal.h>
8: #include petscsys.h
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"
17: /*
18: These are the debugger and display used if the debugger is started up
19: */
20: static char Debugger[256];
21: static PetscTruth Xterm = PETSC_TRUE;
23: /*@C
24: PetscSetDebugger - Sets options associated with the debugger.
26: Not Collective
28: Input Parameters:
29: + debugger - name of debugger, which should be in your path,
30: usually "dbx", "gdb", or "xxgdb". Also, HP-UX
31: supports "xdb", and IBM rs6000 supports "xldb".
33: - xterm - flag to indicate debugger window, set to either 1 (to indicate
34: debugger should be started in a new xterm) or 0 (to start debugger
35: in initial window (the option 0 makes no sense when using more
36: than one processor.)
38: Level: developer
40: Fortran Note:
41: This routine is not supported in Fortran.
43: Concepts: debugger^setting
45: .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
46: @*/
47: int PetscSetDebugger(const char debugger[],PetscTruth xterm)
48: {
52: if (debugger) {
53: PetscStrcpy(Debugger,debugger);
54: }
55: Xterm = xterm;
57: return(0);
58: }
60: int PetscSetDefaultDebugger(void)
61: {
65: #if defined(PETSC_USE_DBX_DEBUGGER)
66: PetscSetDebugger("dbx",PETSC_TRUE);
67: #elif defined(PETSC_USE_XDB_DEBUGGER)
68: PetscSetDebugger("xdb",PETSC_TRUE);
69: #else /* Default is gdb */
70: PetscSetDebugger("gdb",PETSC_TRUE);
71: #endif
72: return(0);
73: }
75: int PetscSetDebuggerFromString(char *string)
76: {
77: int ierr;
78: PetscTruth xterm = PETSC_TRUE;
79: char *f,*debugger = 0;
82: PetscStrstr(string,"noxterm",&f);
83: if (f) xterm = PETSC_FALSE;
84: PetscStrstr(string,"xdb",&f);
85: if (f) debugger = "xdb";
86: PetscStrstr(string,"dbx",&f);
87: if (f) debugger = "dbx";
88: PetscStrstr(string,"xldb",&f);
89: if (f) debugger = "xldb";
90: PetscStrstr(string,"gdb",&f);
91: if (f) debugger = "gdb";
92: PetscStrstr(string,"xxgdb",&f);
93: if (f) debugger = "xxgdb";
94: PetscStrstr(string,"ups",&f);
95: if (f) debugger = "ups";
96: PetscStrstr(string,"workshop",&f);
97: if (f) debugger = "workshop";
98: PetscStrstr(string,"pgdbg",&f);
99: if (f) debugger = "pgdbg";
100: PetscSetDebugger(debugger,xterm);
101: return(0);
102: }
105: /*@C
106: PetscAttachDebugger - Attaches the debugger to the running process.
108: Not Collective
110: Level: advanced
112: Concepts: debugger^starting from program
114: .seealso: PetscSetDebugger()
115: @*/
116: int PetscAttachDebugger(void)
117: {
118: int child=0,sleeptime=0,ierr=0;
119: char program[256],display[256],hostname[64];
123: PetscGetDisplay(display,128);
124: PetscGetProgramName(program,256);
125: if (ierr) {
126: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
127: PetscFunctionReturn(1);
128: }
130: #if defined(PETSC_CANNOT_START_DEBUGGER)
131: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debuggern");
132: (*PetscErrorPrintf)("PETSC ERROR: On Cray run program in Totalview debuggern");
133: (*PetscErrorPrintf)("PETSC ERROR: On Windows use Developer Studio(MSDEV)n");
134: MPI_Finalize();
135: exit(0);
136: #else
137: if (!program[0]) {
138: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program namen");
139: PetscFunctionReturn(1);
140: }
141: child = (int)fork();
142: if (child < 0) {
143: (*PetscErrorPrintf)("PETSC ERROR: Error in fork() attaching debuggern");
144: PetscFunctionReturn(1);
145: }
147: /*
148: Swap role the parent and child. This is (I think) so that control c typed
149: in the debugger goes to the correct process.
150: */
151: if (child) { child = 0; }
152: else { child = (int)getppid(); }
154: if (child) { /* I am the parent, will run the debugger */
155: char *args[9],pid[9];
156: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb,isworkshop;
158: PetscGetHostName(hostname,64);
159: /*
160: We need to send a continue signal to the "child" process on the
161: alpha, otherwise it just stays off forever
162: */
163: #if defined (PETSC_NEED_KILL_FOR_DEBUGGER)
164: kill(child,SIGCONT);
165: #endif
166: sprintf(pid,"%d",child);
168: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
169: PetscStrcmp(Debugger,"ups",&isups);
170: PetscStrcmp(Debugger,"xldb",&isxldb);
171: PetscStrcmp(Debugger,"xdb",&isxdb);
172: PetscStrcmp(Debugger,"dbx",&isdbx);
173: PetscStrcmp(Debugger,"workshop",&isworkshop);
174: if (isxxgdb || isups) {
175: args[1] = program; args[2] = pid; args[3] = "-display";
176: args[0] = Debugger; args[4] = display; args[5] = 0;
177: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
178: if (execvp(args[0],args) < 0) {
179: perror("Unable to start debugger");
180: exit(0);
181: }
182: } else if (isxldb) {
183: args[1] = "-a"; args[2] = pid; args[3] = program; args[4] = "-display";
184: args[0] = Debugger; args[5] = display; args[6] = 0;
185: (*PetscErrorPrintf)("PETSC: Attaching %s to %s %s on %sn",args[0],args[1],pid,hostname);
186: if (execvp(args[0],args) < 0) {
187: perror("Unable to start debugger");
188: exit(0);
189: }
190: } else if (isworkshop) {
191: args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
192: args[0] = Debugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = 0;
193: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on %sn",args[0],pid,hostname);
194: if (execvp(args[0],args) < 0) {
195: perror("Unable to start debugger");
196: exit(0);
197: }
198: } else if (!Xterm) {
199: args[1] = program; args[2] = pid; args[3] = 0;
200: args[0] = Debugger;
201: #if defined(PETSC_USE_P_FOR_DEBUGGER)
202: if (isdbx) {
203: args[1] = "-p";
204: args[2] = pid;
205: args[3] = program;
206: args[4] = 0;
207: }
208: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
209: if (isxdb) {
210: args[1] = "-l";
211: args[2] = "ALL";
212: args[3] = "-P";
213: args[4] = pid;
214: args[5] = program;
215: args[6] = 0;
216: }
217: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
218: if (isdbx) {
219: args[1] = "-a";
220: args[2] = pid;
221: args[3] = 0;
222: }
223: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
224: if (isdbx) {
225: args[1] = "-pid";
226: args[2] = pid;
227: args[3] = program;
228: args[4] = 0;
229: }
230: #endif
231: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on %sn",Debugger,program,pid,hostname);
232: if (execvp(args[0],args) < 0) {
233: perror("Unable to start debugger");
234: exit(0);
235: }
236: } else {
237: if (!display[0]) {
238: args[0] = "xterm"; args[1] = "-e";
239: args[2] = Debugger; args[3] = program;
240: args[4] = pid; args[5] = 0;
241: #if defined(PETSC_USE_P_FOR_DEBUGGER)
242: if (isdbx) {
243: args[3] = "-p";
244: args[4] = pid;
245: args[5] = program;
246: args[6] = 0;
247: }
248: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
249: if (isxdb) {
250: args[5] = program;
251: args[3] = "-P";
252: args[4] = pid;
253: args[6] = 0;
254: }
255: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
256: if (isdbx) {
257: args[3] = "-a";
258: args[4] = pid;
259: args[5] = 0;
260: }
261: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
262: if (isdbx) {
263: args[3] = "-pid";
264: args[4] = pid;
265: args[5] = program;
266: args[6] = 0;
267: }
268: #endif
269: (*PetscErrorPrintf)("PETSC: Attaching %s to %s on pid %s on %sn",Debugger,program,pid,hostname);
270: } else {
271: args[0] = "xterm"; args[1] = "-display";
272: args[2] = display; args[3] = "-e";
273: args[4] = Debugger; args[5] = program;
274: args[6] = pid; args[7] = 0;
275: #if defined(PETSC_USE_P_FOR_DEBUGGER)
276: if (isdbx) {
277: args[5] = "-p";
278: args[6] = pid;
279: args[7] = program;
280: args[8] = 0;
281: }
282: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
283: if (isxdb) {
284: args[7] = program;
285: args[5] = "-P";
286: args[6] = pid;
287: args[8] = 0;
288: }
289: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
290: if (isdbx) {
291: args[5] = "-a";
292: args[6] = pid;
293: args[7] = 0;
294: }
295: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
296: if (isdbx) {
297: args[5] = "-pid";
298: args[6] = pid;
299: args[7] = program;
300: args[8] = 0;
301: }
302: #endif
303: (*PetscErrorPrintf)("PETSC: Attaching %s to %s of pid %s on display %s on machine %sn",Debugger,program,pid,display,hostname);
304: }
306: if (execvp("xterm",args) < 0) {
307: perror("Unable to start debugger");
308: exit(0);
309: }
310: }
311: } else { /* I am the child, continue with user code */
312: sleeptime = 10; /* default to sleep waiting for debugger */
313: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
314: if (sleeptime < 0) sleeptime = -sleeptime;
315: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
316: /*
317: HP cannot attach process to sleeping debugger, hence count instead
318: */
319: {
320: PetscReal x = 1.0;
321: int i=10000000;
322: while (i--) x++ ; /* cannot attach to sleeper */
323: }
324: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
325: /*
326: IBM sleep may return at anytime, hence must see if there is more time to sleep
327: */
328: {
329: int left = sleeptime;
330: while (left > 0) {left = PetscSleep(left) - 1;}
331: }
332: #else
333: PetscSleep(sleeptime);
334: #endif
335: }
336: #endif
337: return(0);
338: }
340: /*@C
341: PetscAttachDebuggerErrorHandler - Error handler that attaches
342: a debugger to a running process when an error is detected.
343: This routine is useful for examining variables, etc.
345: Not Collective
347: Input Parameters:
348: + line - the line number of the error (indicated by __LINE__)
349: . file - the file in which the error was detected (indicated by __FILE__)
350: . dir - the directory of the file (indicated by __SDIR__)
351: . message - an error text string, usually just printed to the screen
352: . number - the generic error number
353: . p - the specific error number
354: - ctx - error handler context
356: Options Database Keys:
357: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
358: debugger attachment
360: Level: developer
362: Notes:
363: By default the GNU debugger, gdb, is used. Alternatives are dbx and
364: xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
366: Most users need not directly employ this routine and the other error
367: handlers, but can instead use the simplified interface SETERR, which has
368: the calling sequence
369: $ SETERRQ(number,p,message)
371: Notes for experienced users:
372: Use PetscPushErrorHandler() to set the desired error handler. The
373: currently available PETSc error handlers are
374: $ PetscTraceBackErrorHandler()
375: $ PetscAttachDebuggerErrorHandler()
376: $ PetscAbortErrorHandler()
377: or you may write your own.
379: Concepts: debugger^error handler
380: Concepts: error handler^attach debugger
382: .seealso: PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
383: PetscAbortErrorHandler()
384: @*/
385: int PetscAttachDebuggerErrorHandler(int line,char* fun,char *file,char* dir,int num,int p,char* mess,void *ctx)
386: {
387: int ierr,rank;
390: if (!fun) fun = "unknownfunction";
391: if (!dir) dir = " ";
392: if (!mess) mess = " ";
394: MPI_Comm_rank(MPI_COMM_WORLD,&rank);
395: (*PetscErrorPrintf)("[%d]PETSC ERROR: %s() line %d in %s%s %sn",rank,fun,line,dir,file,mess);
397: PetscAttachDebugger();
398: if (ierr) { /* hopeless so get out */
399: MPI_Finalize();
400: exit(num);
401: }
402: return(0);
403: }
405: /*@C
406: PetscStopForDebugger - Prints a message to the screen indicating how to
407: attach to the process with the debugger and then waits for the
408: debugger to attach.
410: Not Collective
412: Level: advanced
414: Concepts: debugger^waiting for attachment
416: .seealso: PetscSetDebugger(), PetscAttachDebugger()
417: @*/
418: int PetscStopForDebugger(void)
419: {
420: int sleeptime=0,ierr,ppid,rank;
421: char program[256],hostname[256];
422: PetscTruth isdbx,isxldb,isxxgdb,isups,isxdb;
426: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
427: PetscGetHostName(hostname,256);
428: if (ierr) {
429: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine hostname; just continuing programn");
430: return(0);
431: }
433: PetscGetProgramName(program,256);
434: if (ierr) {
435: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
436: return(0);
437: }
439: #if defined(PETSC_CANNOT_START_DEBUGGER)
440: (*PetscErrorPrintf)("PETSC ERROR: System cannot start debugger; just continuing programn");
441: #else
442: if (!program[0]) {
443: (*PetscErrorPrintf)("PETSC ERROR: Cannot determine program name; just continuing programn");
444: return(0);
445: }
447: ppid = getpid();
449: PetscStrcmp(Debugger,"xxgdb",&isxxgdb);
450: PetscStrcmp(Debugger,"ups",&isups);
451: PetscStrcmp(Debugger,"xldb",&isxldb);
452: PetscStrcmp(Debugger,"xdb",&isxdb);
453: PetscStrcmp(Debugger,"dbx",&isdbx);
455: if (isxxgdb || isups) {
456: (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
457: }
458: #if defined(PETSC_USE_A_FOR_DEBUGGER)
459: else if (isxldb) {
460: (*PetscErrorPrintf)("{%d]%s>>%s -a %d %sn",rank,hostname,Debugger,ppid,program);
461: }
462: #endif
463: #if defined(PETSC_USE_P_FOR_DEBUGGER)
464: else if (isdbx) {
465: (*PetscErrorPrintf)("[%d]%s>>%s -p %d %sn",rank,hostname,Debugger,ppid,program);
466: }
467: #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
468: else if (isxdb) {
469: (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %sn",rank,hostname,Debugger,ppid,program);
470: }
471: #elif defined(PETSC_USE_A_FOR_DEBUGGER)
472: else if (isdbx) {
473: (*PetscErrorPrintf)("[%d]%s>>%s -a %dn",rank,hostname,Debugger,ppid);
474: }
475: #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
476: else if (isdbx) {
477: (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %sn",rank,hostname,Debugger,ppid,program);
478: }
479: #else
480: else {
481: (*PetscErrorPrintf)("[%d]%s>>%s %s %dn",rank,hostname,Debugger,program,ppid);
482: }
483: #endif
484: #endif /* PETSC_CANNOT_START_DEBUGGER */
486: fflush(stdout);
488: sleeptime = 25; /* default to sleep waiting for debugger */
489: PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL);
490: if (sleeptime < 0) sleeptime = -sleeptime;
491: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
492: /*
493: HP cannot attach process to sleeping debugger, hence count instead
494: */
495: {
496: PetscReal x = 1.0;
497: int i=10000000;
498: while (i--) x++ ; /* cannot attach to sleeper */
499: }
500: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
501: /*
502: IBM sleep may return at anytime, hence must see if there is more time to sleep
503: */
504: {
505: int left = sleeptime;
506: while (left > 0) {left = sleep(left) - 1;}
507: }
508: #else
509: PetscSleep(sleeptime);
510: #endif
511: return(0);
512: }