Added flag "-debug" to charmc for usage with charmdebug.
[charm.git] / src / ck-core / debug-charm.C
1 /*****************************************************************************
2  * A few useful built-in CPD and CCS handlers.
3  *****************************************************************************/
4
5 #include "converse.h"
6
7 #include <errno.h>
8 #include <string.h>
9 #include <sys/stat.h>           // for chmod
10
11 #include "ckhashtable.h"
12 #include "conv-ccs.h"
13 #include "debug-charm.h"
14 #include "sockRoutines.h"
15 #include "charm.h"
16 #include "middle.h"
17 #include "cklists.h"
18 #include "register.h"
19 //#include "queueing.h"
20
21 #if CMK_CCS_AVAILABLE && !defined(_WIN32)
22
23 #include "ck.h"
24
25
26 /************ Array Element CPD Lists ****************/
27
28 /**
29   Count array elements going by until they reach this 
30   range (lo to hi), then start passing them to dest.
31 */
32 template <class T>
33 class CkArrayElementRangeIterator : public CkLocIterator {
34 private:
35    T *dest;
36    CkArray *mgr;
37    int cur,lo,hi;
38 public:
39    CkArrayElementRangeIterator(T *dest_,int l,int h) 
40         :dest(dest_),mgr(0),cur(0),lo(l),hi(h) {}
41    
42   /** Called to iterate only on a specific array manager.
43       Returs the number of objects it iterate on.
44   */
45   int iterate(int start, CkArray *m) {
46     cur = start;
47     mgr = m;
48     mgr->getLocMgr()->iterate(*this);
49     cur -= start;
50     return cur;
51   }
52
53    /** Call add for every in-range array element on this processor */
54    void iterate(void)
55    { /* Walk the groupTable for arrays (FIXME: get rid of _groupIDTable) */
56      int numGroups=CkpvAccess(_groupIDTable)->size();
57      for(int i=0;i<numGroups;i++) {
58         IrrGroup *obj = CkpvAccess(_groupTable)->find((*CkpvAccess(_groupIDTable))[i]).getObj();
59         if (obj->isArrMgr()) 
60         { /* This is an array manager: examine its array elements */
61           mgr=(CkArray *)obj;
62           mgr->getLocMgr()->iterate(*this);
63         }
64      }
65    }
66    
67    // Called by location manager's iterate function
68    virtual void addLocation (CkLocation &loc)
69    {
70      if (cur>=lo && cur<hi) 
71      { /* This element is in our range-- look it up */
72        dest->add(cur,mgr->lookup(loc.getIndex()),mgr->getGroupID().idx);
73      }
74      cur++;
75    }
76    
77    // Return the number of total array elements seen so far.
78    int getCount(void) {return cur;}
79 };
80
81 /**
82   Count charm++ objects going by until they reach this 
83   range (lo to hi), then start passing them to dest.
84 */
85 template <class T>
86 class CkObjectRangeIterator {
87 private:
88    T *dest;
89    int cur,lo,hi;
90 public:
91    CkObjectRangeIterator(T *dest_,int l,int h) 
92         :dest(dest_),cur(0),lo(l),hi(h) {}
93    
94    /** Call add for every in-range array element on this processor */
95    void iterate(void)
96    { /* Walk the groupTable for arrays (FIXME: get rid of _groupIDTable) */
97      int numGroups=CkpvAccess(_groupIDTable)->size();
98      for(int i=0;i<numGroups;i++) {
99         IrrGroup *obj = CkpvAccess(_groupTable)->find((*CkpvAccess(_groupIDTable))[i]).getObj();
100         /*if (obj->isArrMgr()) 
101         { / * This is an array manager: examine its array elements * /
102           CkArray *mgr=(CkArray *)obj;
103           CkArrayElementRangeIterator<T> ait(dest,lo,hi);
104           ait.iterate(cur, mgr);
105           cur+=ait.getCount();
106         } else {*/
107           dest->add(cur,obj,i);
108           cur++;
109         //}
110      }
111    }
112    
113    // Return the number of total array elements seen so far.
114    int getCount(void) {return cur;}
115 };
116
117 class ignoreAdd {
118 public: void add(int cur,Chare *elt,int group) {}
119 };
120
121 /** Examine all the objects on the server returning the name */
122 class CpdList_objectNames : public CpdListAccessor {
123   PUP::er *pp; // Only used while inside pup routine.
124   int curGroup;
125 public:
126   virtual const char * getPath(void) const {return "charm/objectNames";}
127   virtual int getLength(void) const {
128     CkObjectRangeIterator<ignoreAdd> it(0,0,0);
129     it.iterate();
130     return it.getCount();
131   }
132   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
133     pp=&p;
134     CkObjectRangeIterator<CpdList_objectNames> it(this,req.lo,req.hi);
135     it.iterate(); // calls "add" for in-range elements
136   }
137   void add(int cur, Chare *obj, int group) {
138     PUP::er &p=*pp;
139     beginItem(p,cur);
140     p.comment("id");
141     char *n = (char*)malloc(30);
142     int s=obj->ckDebugChareID(n, 30);
143     CkAssert(s > 0);
144     p(n,s);
145     free(n);
146     PUPn(group);
147     p.comment("name");
148     n=obj->ckDebugChareName();
149     p(n,strlen(n));
150     free(n);
151   }
152 };
153
154 /** Examine a single object identified by the id passed in the request and
155     return its type and memory data */
156 class CpdList_object : public CpdListAccessor {
157   PUP::er *pp; //Only used while inside pup routine.
158   CpdListItemsRequest *reqq; // Only used while inside pup routine.
159 public:
160   virtual const char * getPath(void) const {return "charm/object";}
161   virtual int getLength(void) const {
162     CkObjectRangeIterator<ignoreAdd> it(0,0,0);
163     it.iterate();
164     return it.getCount();
165   }
166   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
167     pp=&p;
168     reqq=&req;
169     CkObjectRangeIterator<CpdList_object> it(this,req.lo,req.hi);
170     it.iterate(); // calls "add" for in-range elements;
171   }
172   void add(int cur, Chare *obj, int group) {
173     PUP::er &p=*pp;
174     CpdListItemsRequest &req=*reqq;
175     char *n = (char *)malloc(30);
176     int s=obj->ckDebugChareID(n, 30);
177     CkAssert(s > 0);
178     if (req.extraLen == s && memcmp(req.extra, n, s) == 0) {
179       // the object match, found!
180       beginItem(p,cur);
181       int type = obj->ckGetChareType();
182       p.comment("type");
183       const char *t = _chareTable[type]->name;
184       p((char*)t,strlen(t));
185       p.comment("value");
186       int size = _chareTable[type]->size;
187       p((char*)obj,size);
188     }
189   }
190 };
191
192 /** Coarse: examine array element names */
193 class CpdList_arrayElementNames : public CpdListAccessor {
194   PUP::er *pp; // Only used while inside pup routine.
195 public:
196   virtual const char * getPath(void) const {return "charm/arrayElementNames";}
197   virtual int getLength(void) const {
198     CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
199     it.iterate();
200     return it.getCount();
201   }
202   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
203     pp=&p;
204     CkArrayElementRangeIterator<CpdList_arrayElementNames> it(this,req.lo,req.hi);
205     it.iterate(); // calls "add" for in-range elements
206   }
207   void add(int cur,Chare *e,int group) 
208   { // Just grab the name and nothing else:
209     ArrayElement *elt = (ArrayElement*)e;
210          PUP::er &p=*pp;
211          beginItem(p,cur);
212          p.comment("name");
213          char *n=elt->ckDebugChareName();
214          p(n,strlen(n));
215          free(n);
216   }
217 };
218
219 /** Detailed: examine array element data */
220 class CpdList_arrayElements : public CpdListAccessor {
221   PUP::er *pp; // Only used while inside pup routine.
222 public:
223   virtual const char * getPath(void) const {return "charm/arrayElements";}
224   virtual int getLength(void) const {
225     CkArrayElementRangeIterator<ignoreAdd> it(0,0,0);
226     it.iterate();
227     return it.getCount();
228   }
229   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
230     pp=&p;
231     CkArrayElementRangeIterator<CpdList_arrayElements> it(this,req.lo,req.hi);
232     it.iterate(); // calls "add" for in-range elements
233   }
234   void add(int cur, Chare *e, int group) 
235   { // Pup the element data
236     ArrayElement *elt = (ArrayElement*)e;
237     PUP::er &p=*pp;
238     beginItem(p,cur);
239     //elt->ckDebugPup(p);
240     // Now ignore any pupper, just copy all the memory as raw data
241     p.comment("name");
242     char *n=elt->ckDebugChareName();
243     p(n,strlen(n));
244     free(n);
245     int type = elt->ckGetChareType();
246     p.comment("type");
247     const char *t = _chareTable[type]->name;
248     p((char*)t,strlen(t));
249     p.comment("value");
250     int size = _chareTable[type]->size;
251     p((char*)elt,size);
252   }
253 };
254
255 #ifndef __CYGWIN__
256 #include <rpc/rpc.h>
257 #endif
258
259 int hostInfoLength(void *) {return 1;}
260
261 void hostInfo(void *itemIter, pup_er pp, CpdListItemsRequest *req) {
262   PUP::er &p = *(PUP::er *)pp;
263   struct sockaddr_in addr;
264   CpdListBeginItem(pp, 0);
265 #if CMK_HAS_GET_MYADDRESS
266   get_myaddress(&addr);
267 #else
268   CmiAbort("hostInfo: get_myaddress does not work on this machine");
269 #endif
270   char *address = (char*)&addr.sin_addr.s_addr;
271   PUPv(address, 4);
272   int pid = getpid();
273   PUPn(pid);
274 }
275
276 /************ Message CPD Lists ****************/
277 CpvCExtern(void *,debugQueue);
278 CpvCExtern(int, skipBreakpoint);
279
280 // Interpret data in a message in a user-friendly way.
281 //  Ignores most of the envelope fields used by CkPupMessage,
282 //  and instead concentrates on user data
283 void CpdPupMessage(PUP::er &p, void *msg)
284 {
285   envelope *env=UsrToEnv(msg);
286   //int wasPacked=env->isPacked();
287   int size=env->getTotalsize();
288   int prioBits=env->getPriobits();
289   int from=env->getSrcPe();
290   PUPn(from);
291   //PUPn(wasPacked);
292   PUPn(prioBits);
293   int userSize=size-sizeof(envelope)-sizeof(int)*CkPriobitsToInts(prioBits);
294   PUPn(userSize);
295   int msgType = env->getMsgIdx();
296   PUPn(msgType);
297   int msgFor = env->getMsgtype();
298   PUPn(msgFor);
299
300   //p.synchronize(PUP::sync_last_system);
301   
302   int ep=CkMessageToEpIdx(msg);
303   PUPn(ep);
304   
305   /* user data */
306   p.comment("data");
307   p.synchronize(PUP::sync_begin_object);
308   if (_entryTable[ep]->messagePup!=NULL) 
309     _entryTable[ep]->messagePup(p,msg);
310   else
311     CkMessage::ckDebugPup(p,msg);
312   p.synchronize(PUP::sync_end_object);
313 }
314
315 CpvStaticDeclare(void *, lastBreakPointMsg);
316
317 //Cpd Lists for local and scheduler queues
318 class CpdList_localQ : public CpdListAccessor {
319
320 public:
321   CpdList_localQ() {}
322   virtual const char * getPath(void) const {return "converse/localqueue";}
323   virtual int getLength(void) const {
324     int x = CdsFifo_Length((CdsFifo)(CpvAccess(debugQueue)));
325     //CmiPrintf("*******Returning fifo length %d*********\n", x);
326     //return CdsFifo_Length((CdsFifo)(CpvAccess(CmiLocalQueue)));
327     if (CpvAccess(lastBreakPointMsg) != NULL) x++;
328     return x;
329   }
330   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
331     int length = CdsFifo_Length((CdsFifo)(CpvAccess(debugQueue)));
332     void ** messages = CdsFifo_Enumerate(CpvAccess(debugQueue));
333     int curObj=0;
334
335     if (CpvAccess(lastBreakPointMsg) != NULL) {
336       beginItem(p, -1);
337       envelope *env=(envelope *)UsrToEnv(CpvAccess(lastBreakPointMsg));
338       p.comment("name");
339       char *type="Breakpoint";
340       p(type,strlen(type));
341       p.comment("charmMsg");
342       p.synchronize(PUP::sync_begin_object);
343       CkUnpackMessage(&env);
344       CpdPupMessage(p, EnvToUsr(env));
345       p.synchronize(PUP::sync_end_object);
346     }
347     
348     for(curObj=req.lo; curObj<req.hi; curObj++)
349       if ((curObj>=0) && (curObj<length))
350       {
351         beginItem(p,curObj);
352         void *msg=messages[curObj]; /* converse message */
353         int isCharm=0;
354         const char *type="Converse";
355         p.comment("name");
356         char name[128];
357         if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";}
358         if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";}
359         sprintf(name,"%s %d: %s (%d)","Message",curObj,type,CmiGetHandler(msg));
360         p(name, strlen(name));
361         
362         if (isCharm) 
363         { /* charm message */
364           p.comment("charmMsg");
365           p.synchronize(PUP::sync_begin_object);
366           envelope *env=(envelope *)msg;
367           CkUnpackMessage(&env);
368           messages[curObj]=env;
369           CpdPupMessage(p, EnvToUsr(env));
370           //CkPupMessage(p, &messages[curObj], 0);
371           p.synchronize(PUP::sync_end_object);
372         }
373       }
374     delete[] messages;
375
376   }
377 };
378
379
380 /****************** Breakpoints and other debug support **************/
381
382 typedef CkHashtableTslow<int,EntryInfo *> CpdBpFuncTable_t;
383
384
385 extern void CpdFreeze(void);
386 extern void CpdUnFreeze(void);
387 extern int  CpdIsFrozen(void);
388
389 CpvStaticDeclare(int, _debugMsg);
390 CpvStaticDeclare(int, _debugChare);
391
392 CpvStaticDeclare(CpdBpFuncTable_t *, breakPointEntryTable);
393
394 //CpvStaticDeclare(void *, lastBreakPointMsg);
395 CpvStaticDeclare(void *, lastBreakPointObject);
396 CpvStaticDeclare(int, lastBreakPointIndex);
397
398 void CpdBreakPointInit()
399 {
400   CpvInitialize(void *, lastBreakPointMsg);
401   CpvInitialize(void *, lastBreakPointObject);
402   CpvInitialize(int, lastBreakPointIndex);
403   CpvInitialize(int, _debugMsg);
404   CpvInitialize(int, _debugChare);
405   CpvInitialize(CpdBpFuncTable_t *, breakPointEntryTable);
406   CpvAccess(lastBreakPointMsg) = NULL;
407   CpvAccess(lastBreakPointObject) = NULL;
408   CpvAccess(lastBreakPointIndex) = 0;
409   CpvAccess(_debugMsg) = CkRegisterMsg("debug_msg",0,0,0);
410   CpvAccess(_debugChare) = CkRegisterChare("debug_Chare",0);
411   CkRegisterChareInCharm(CpvAccess(_debugChare));
412   CpvAccess(breakPointEntryTable) = new CpdBpFuncTable_t(10,0.5,CkHashFunction_int,CkHashCompare_int );
413 }
414
415
416
417 static void _call_freeze_on_break_point(void * msg, void * object)
418 {
419       //Save breakpoint entry point index. This is retrieved from msg.
420       //So that the appropriate EntryInfo can be later retrieved from the hash table 
421       //of break point function entries, on continue.
422   
423   // If the counter "skipBreakpoint" is not zero we actually do not freeze and deliver the regular message
424   if (CpvAccess(skipBreakpoint) > 0) {
425     EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkMessageToEpIdx(msg));
426     CkAssert(breakPointEntryInfo != NULL);
427     breakPointEntryInfo->call(msg, object);
428     CpvAccess(skipBreakpoint) --;
429   } else {
430       CpvAccess(lastBreakPointMsg) = msg;
431       CpvAccess(lastBreakPointObject) = object;
432       CpvAccess(lastBreakPointIndex) = CkMessageToEpIdx(msg);
433       EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
434       CmiPrintf("Break point reached for Function = %s\n", breakPointEntryInfo->name);
435       CpdFreeze();
436   }
437 }
438
439 //ccs handler when pressed the "next" command: deliver only a single message without unfreezing
440 extern "C"
441 void CpdDeliverSingleMessage () {
442   if (!CpdIsFrozen()) return; /* Do something only if we are in freeze mode */
443   if ( (CpvAccess(lastBreakPointMsg) != NULL) && (CpvAccess(lastBreakPointObject) != NULL) ) {
444     EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
445     if (breakPointEntryInfo != NULL) {
446       breakPointEntryInfo->call(CpvAccess(lastBreakPointMsg), CpvAccess(lastBreakPointObject));
447     }
448     CpvAccess(lastBreakPointMsg) = NULL;
449     CpvAccess(lastBreakPointObject) = NULL;
450   }
451   else {
452     // we were not stopped at a breakpoint, then deliver the first message in the debug queue
453     if (!CdsFifo_Empty(CpvAccess(debugQueue))) {
454       CpvAccess(skipBreakpoint) = 1;
455       char *queuedMsg = (char *)CdsFifo_Dequeue(CpvAccess(debugQueue));
456       CmiHandleMessage(queuedMsg);
457       CpvAccess(skipBreakpoint) = 0;
458     }
459   }
460 }
461
462 //ccs handler when continue from a break point
463 extern "C"
464 void CpdContinueFromBreakPoint ()
465 {
466     CpdUnFreeze();
467     if ( (CpvAccess(lastBreakPointMsg) != NULL) && (CpvAccess(lastBreakPointObject) != NULL) )
468     {
469         EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
470         if (breakPointEntryInfo != NULL)
471            breakPointEntryInfo->call(CpvAccess(lastBreakPointMsg), CpvAccess(lastBreakPointObject));
472     }
473     CpvAccess(lastBreakPointMsg) = NULL;
474     CpvAccess(lastBreakPointObject) = NULL;
475 }
476
477 //ccs handler to set a breakpoint with entry function name msg
478 void CpdSetBreakPoint (char *msg)
479 {
480   char functionName[128];
481   int tableSize, tableIdx = 0;
482   sscanf(msg+CmiMsgHeaderSizeBytes, "%s", functionName);
483   if (strlen(functionName) > 0)
484   {
485     tableSize = _entryTable.size();
486     // Replace entry in entry table with _call_freeze_on_break_point
487     // retrieve epIdx for entry method
488     //for (tableIdx=0; tableIdx < tableSize; tableIdx++)
489     //{
490        //if (strstr(_entryTable[tableIdx]->name, functionName) != NULL)
491        //{
492     tableIdx = atoi(functionName);
493     if (tableIdx < 0 || tableIdx >= tableSize) {
494       CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
495       return;
496     }
497             EntryInfo * breakPointEntryInfo = new EntryInfo(_entryTable[tableIdx]->name, _entryTable[tableIdx]->call, _entryTable[tableIdx]->msgIdx, _entryTable[tableIdx]->chareIdx );
498            CmiPrintf("Breakpoint is set for function %s with an epIdx = %ld\n", _entryTable[tableIdx]->name, tableIdx);
499            CpvAccess(breakPointEntryTable)->put(tableIdx) = breakPointEntryInfo;  
500            _entryTable[tableIdx]->name = "debug_breakpoint_ep";  
501            _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
502            _entryTable[tableIdx]->msgIdx = CpvAccess(_debugMsg); 
503            _entryTable[tableIdx]->chareIdx = CpvAccess(_debugChare);
504            //break;
505        //}
506     //}
507     //if (tableIdx == tableSize)
508     //{
509     //  CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
510     //  return;
511     //}
512
513   }
514
515 }
516
517 void CpdQuitDebug()
518 {
519   CpdContinueFromBreakPoint();
520   CkExit();
521 }
522
523 void CpdRemoveBreakPoint (char *msg)
524 {
525   char functionName[128];
526   sscanf(msg+CmiMsgHeaderSizeBytes, "%s", functionName);
527   if (strlen(functionName) > 0) {
528   int idx = atoi(functionName);
529   if (idx < 0 || idx >= _entryTable.size()) {
530     CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
531     return;
532   }
533   //void *objPointer;
534   //void *keyPointer; 
535   //CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
536   //while(NULL!=(objPointer = it->next(&keyPointer)))
537   //{
538   //EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
539   EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(idx);
540     //int idx = *(int *)keyPointer;
541     //if (strstr(breakPointEntryInfo->name, functionName) != NULL){
542         _entryTable[idx]->name =  breakPointEntryInfo->name;
543         _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
544         _entryTable[idx]->msgIdx = breakPointEntryInfo->msgIdx;
545         _entryTable[idx]->chareIdx = breakPointEntryInfo->chareIdx;
546         CmiPrintf("Breakpoint is removed for function %s with epIdx %ld\n", _entryTable[idx]->name, idx);
547     //}
548   //}
549   }
550 }
551
552 void CpdRemoveAllBreakPoints ()
553 {
554   //all breakpoints removed
555   void *objPointer;
556   void *keyPointer; 
557   CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
558   while(NULL!=(objPointer = it->next(&keyPointer)))
559   {
560     EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
561     int idx = *(int *)keyPointer;
562     _entryTable[idx]->name =  breakPointEntryInfo->name;
563     _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
564     _entryTable[idx]->msgIdx = breakPointEntryInfo->msgIdx;
565     _entryTable[idx]->chareIdx = breakPointEntryInfo->chareIdx;
566   }
567 }
568
569 extern "C" CmiBool isDebugMessage(void *msg) {
570   envelope *env = (envelope*)msg;
571   // Later should use "isDebug" value, but for now just bypass all intrinsic EPs
572   return _entryTable[env->getEpIdx()]->inCharm;
573 }
574
575
576
577 CpvExtern(char *, displayArgument);
578
579 void CpdStartGdb(void)
580 {
581 #if !defined(_WIN32) || defined(__CYGWIN__)
582   FILE *f;
583   char gdbScript[200];
584   int pid;
585   if (CpvAccess(displayArgument) != NULL)
586   {
587      /*CmiPrintf("MY NODE IS %d  and process id is %d\n", CmiMyPe(), getpid());*/
588      sprintf(gdbScript, "/tmp/cpdstartgdb.%d.%d", getpid(), CmiMyPe());
589      f = fopen(gdbScript, "w");
590      fprintf(f,"#!/bin/sh\n");
591      fprintf(f,"cat > /tmp/start_gdb.$$ << END_OF_SCRIPT\n");
592      fprintf(f,"shell /bin/rm -f /tmp/start_gdb.$$\n");
593      //fprintf(f,"handle SIGPIPE nostop noprint\n");
594      fprintf(f,"handle SIGWINCH nostop noprint\n");
595      fprintf(f,"handle SIGWAITING nostop noprint\n");
596      fprintf(f, "attach %d\n", getpid());
597      fprintf(f,"END_OF_SCRIPT\n");
598      fprintf(f, "DISPLAY='%s';export DISPLAY\n",CpvAccess(displayArgument));
599      fprintf(f,"/usr/X11R6/bin/xterm ");
600      fprintf(f," -title 'Node %d ' ",CmiMyPe());
601      fprintf(f," -e /usr/bin/gdb -x /tmp/start_gdb.$$ \n");
602      fprintf(f, "exit 0\n");
603      fclose(f);
604      if( -1 == chmod(gdbScript, 0755))
605      {
606         CmiPrintf("ERROR> chmod on script failed!\n");
607         return;
608      }
609      pid = fork();
610      if (pid < 0)
611         { perror("ERROR> forking to run debugger script\n"); exit(1); }
612      if (pid == 0)
613      {
614          //CmiPrintf("In child process to start script %s\n", gdbScript);
615  if (-1 == execvp(gdbScript, NULL))
616             CmiPrintf ("Error> Could not Execute Debugger Script: %s\n",strerror
617 (errno));
618
619       }
620     }
621 #endif
622 }
623
624 void CpdCharmInit()
625 {
626   CpdBreakPointInit();
627   CcsRegisterHandler("ccs_set_break_point",(CmiHandler)CpdSetBreakPoint);
628   CcsRegisterHandler("ccs_remove_break_point",(CmiHandler)CpdRemoveBreakPoint);
629   CcsRegisterHandler("ccs_remove_all_break_points",(CmiHandler)CpdRemoveAllBreakPoints);
630   CcsRegisterHandler("ccs_continue_break_point",(CmiHandler)CpdContinueFromBreakPoint);
631   CcsRegisterHandler("ccs_single_step",(CmiHandler)CpdDeliverSingleMessage);
632   CcsRegisterHandler("ccs_debug_quit",(CmiHandler)CpdQuitDebug);
633   CcsRegisterHandler("ccs_debug_startgdb",(CmiHandler)CpdStartGdb);
634   CpdListRegister(new CpdListAccessor_c("hostinfo",hostInfoLength,0,hostInfo,0));
635   CpdListRegister(new CpdList_localQ());
636   CpdListRegister(new CpdList_arrayElementNames());
637   CpdListRegister(new CpdList_arrayElements());
638   CpdListRegister(new CpdList_objectNames());
639   CpdListRegister(new CpdList_object());
640 }
641
642 #else
643
644 void CpdCharmInit()
645 {
646 }
647
648 #endif /*CMK_CCS_AVAILABLE*/