Problem 1:
[dyninst.git] / dyninstAPI / src / EventHandler.C
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  *
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  *
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  *
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  *
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  *
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  *
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42
43 #if defined(__XLC__) || defined(__xlC__)
44 #include "common/h/EventHandler.h"
45 #else
46 #if !defined (os_windows)
47 #pragma implementation "EventHandler.h"
48 #endif
49 #endif
50
51 #include "mailbox.h"
52 #include "BPatch_eventLock.h"
53 #include "util.h"
54 #include "common/h/Vector.h"
55 #include "debuggerinterface.h"
56 #include "process.h"
57
58
59 pdvector< pdpair <unsigned long, const char *> > threadmap;
60 const char *getThreadStr(unsigned long tid)
61 {
62   if (!threadmap.size() && (getExecThreadID() == primary_thread_id)) {
63     pdpair<unsigned long, const char *> trec;
64 #if defined(os_windows)
65     trec.first = (unsigned long) _threadid;
66 #else
67     trec.first = (unsigned long) pthread_self();
68 #endif
69     trec.second = "UI";
70     threadmap.push_back(trec);
71   }
72
73   for (unsigned int i = 0; i < threadmap.size(); ++i) {
74     if (threadmap[i].first == tid)
75       return threadmap[i].second;
76   }
77   if (tid == (unsigned long) -1L) 
78     return "any_thread";
79   fprintf(stderr, "%s[%d]:  FIXME, no entry found for thread id %lu\n", __FILE__, __LINE__, tid);
80   return "invalid";
81 }
82
83 unsigned long getExecThreadID() 
84 {
85 #if defined (os_windows)
86   return (unsigned long) _threadid;
87 #else
88   return (unsigned long) pthread_self();
89 #endif
90 }
91
92 EventRecord::EventRecord() :
93       proc(NULL), 
94       lwp(NULL), 
95       type(evtUndefined), 
96       what(0),
97       status(NULL_STATUS_INITIALIZER),
98       address(0), 
99       fd(0)
100 {
101 #if defined (os_windows)
102   info.dwDebugEventCode = 0;
103   info.dwProcessId = 0;
104   info.dwThreadId = 0;
105 #else
106   info = 0;
107 #endif
108 }
109
110 char *EventRecord::sprint_event(char *buf)
111  {
112     int pid = -1;
113     if (proc && proc->sh && proc->status() != deleted) pid = proc->getPid();
114     sprintf(buf, "[%s:proc=%d:lwp=%d:%d:%d:%p:%d]", eventType2str(type),
115             pid, lwp ? lwp->get_lwp_id() : 0, what,
116             (int) status, (void *) address, fd);
117     return buf;
118 }
119
120 bool EventRecord::isTemplateOf(EventRecord &src) 
121 {
122      //  returns true if key non-default member values match src
123      if ((type != src.type) && (type != evtAnyEvent) && (type != evtUndefined)) {
124        return false; 
125      }
126      //  maybe we should compare pid instead of proc ptr??
127      if ((proc != src.proc) && (proc != NULL)) {
128        return false;
129      }
130      //  maybe we should compare lwpid instead of lwp ptr??
131      if ((lwp != src.lwp) && (lwp != NULL)) {
132        return false;
133      }
134      if ((what != src.what) && (what != 0)){
135        return false;
136      }
137      if ((status != src.status) && (status != NULL_STATUS_INITIALIZER)) {
138        return false;
139      }
140 #if 0
141     // dont want to compare info, since this is either the raw status output
142     // from waitpid (or waitForDebugEvent), or the argument from a runtime
143     // library call -- eg the pid of a forked process.
144
145      if ((info != src.info) && (info != NULL_INFO_INITIALIZER)) {
146        return false;
147      }
148 #endif
149
150      return true;
151 }
152
153 //  A wrapper for pthread_create, or its equivalent.
154
155 inline THREAD_RETURN eventHandlerWrapper(void *h)
156 {
157   startup_printf("%s[%d]:  about to call main() for %s\n", __FILE__, __LINE__, ((EventHandler<EventRecord> *)h)->idstr);
158   ((EventHandler<EventRecord> * )h)->main();
159   DO_THREAD_RETURN;
160 }
161
162 InternalThread::InternalThread(const char *id) :
163 //template <class S>
164 //InternalThread<S>::InternalThread(const char *id) :
165   _isRunning(false),
166   tid ((unsigned long ) -1),
167   init_ok(true)
168 {
169   idstr = strdup(id);
170 }
171
172 InternalThread::~InternalThread() 
173 //template <class S>
174 //InternalThread<S>::~InternalThread() 
175 {
176   if (isRunning()) {
177     //if (!killThread()) {
178     //   fprintf(stderr, "%s[%d]:  failed to terminate internalThread\n", __FILE__, __LINE__);
179    // }
180   }
181   tid = (unsigned long) -1L;
182   free (idstr);
183 }
184
185 bool InternalThread::createThread()
186 //template <class S>
187 //bool InternalThread<S>::createThread()
188 {
189   mailbox_printf("%s[%d]  welcome to createThread(%s)\n", __FILE__, __LINE__, idstr);
190   if (isRunning()) {
191      fprintf(stderr, "%s[%d]:  WARNING:  cannot create thread '%s'which is already running\n", 
192              __FILE__, __LINE__, idstr);
193      return true;
194   }
195   
196   startupLock = new eventLock();
197   startupLock->_Lock(__FILE__, __LINE__);
198
199 #if defined(os_windows)
200   fprintf(stderr, "%s[%d]:  about to start thread\n", __FILE__, __LINE__);
201   handler_thread = _beginthread(eventHandlerWrapper, 0, (void *) this);
202   if (-1L == handler_thread) {
203     bperr("%s[%d]:  _beginthread(...) failed\n", __FILE__, __LINE__);
204     fprintf(stderr,"%s[%d]:  _beginthread(...) failed\n", __FILE__, __LINE__);
205     return false;
206   }
207 #else  // Unixes
208
209   int err = 0;
210   pthread_attr_t handler_thread_attr;
211
212   err = pthread_attr_init(&handler_thread_attr);
213   if (err) {
214     bperr("%s[%d]:  could not init async handler thread attributes: %s, %d\n",
215           __FILE__, __LINE__, strerror(err), err);
216     return false;
217   }
218
219 #if defined (os_solaris) 
220   err = pthread_attr_setdetachstate(&handler_thread_attr, PTHREAD_CREATE_DETACHED);
221   if (err) {
222     bperr("%s[%d]:  could not set async handler thread attrixibcutes: %s, %d\n",
223           __FILE__, __LINE__, strerror(err), err);
224     return false;
225   }
226 #endif
227   try {
228   err = pthread_create(&handler_thread, &handler_thread_attr,
229                        &eventHandlerWrapper, (void *) this);
230   if (err) {
231     bperr("%s[%d]:  could not start async handler thread: %s, %d\n",
232           __FILE__, __LINE__, strerror(err), err);
233     fprintf(stderr,"%s[%d]:  could not start async handler thread: %s, %d\n",
234           __FILE__, __LINE__, strerror(err), err);
235     return false;
236   }
237   } catch(...) {
238     assert(0);
239   }
240
241   err = pthread_attr_destroy(&handler_thread_attr);
242   if (err) {
243     bperr("%s[%d]:  could not destroy async handler attr: %s, %d\n",
244           __FILE__, __LINE__, strerror(err), err);
245     return false;
246   }
247 #endif
248
249   while (!_isRunning && (init_ok)) {
250     startup_printf("%s[%d]:  createThread (%s) waiting for thread main to start\n", __FILE__, __LINE__, idstr);
251    startupLock->_WaitForSignal(__FILE__, __LINE__);
252    startup_printf("%s[%d]:  createThread (%s) got signal\n", __FILE__, __LINE__, idstr);
253   }
254   startupLock->_Unlock(__FILE__, __LINE__);
255
256   if (!init_ok) {
257     fprintf(stderr, "%s[%d]:  init failed for thread %s\n", FILE__, __LINE__, idstr);
258     return false;
259   }
260   return true;
261
262 }
263
264 bool InternalThread::killThread()
265 //template <class S>
266 //bool InternalThread<S>::killThread()
267 {
268   if (!isRunning()) {
269     fprintf(stderr, "%s[%d]:  request to kill already-stopped thread\n", __FILE__, __LINE__);
270     return true;
271   }
272
273 #if defined(os_windows)
274   fprintf(stderr, "%s[%d]:  cannot kill threads on windows\n", __FILE__, __LINE__);
275   return false;
276 #else
277   int killres;
278   killres = pthread_kill(handler_thread, 9);
279   if (killres) {
280      fprintf(stderr, "%s[%d]:  pthread_kill: %s[%d]\n", __FILE__, __LINE__,
281              strerror(killres), killres);
282      return false;
283   }
284   fprintf(stderr, "%s[%d]:  \t\t..... killed.\n", __FILE__, __LINE__);
285   _isRunning = false;
286 #endif
287   return true; 
288 }
289
290 //template class InternalThread<EventRecord>;
291 //template class InternalThread<DBIEvent>;
292
293 template <class T>
294 EventHandler<T>::EventHandler(eventLock *_lock, const char *id, bool create) :
295   //InternalThread<T>(id),
296   InternalThread(id),
297   eventlock(_lock),
298   stop_request(false)
299 {
300   //  presume that event handler is created on the ui thread, so make an entry
301   if (!threadmap.size()) {
302     pdpair<unsigned long, const char *> trec;
303     trec.first = getExecThreadID();
304     trec.second = "UI";
305     threadmap.push_back(trec);
306   }
307   if (create) 
308     if (!createThread()) {
309       fprintf(stderr, "%s[%d]:  failed to create InternalThread\n", __FILE__, __LINE__);
310     }
311 }
312
313 template <class T>
314 EventHandler<T>::~EventHandler()
315 {
316 }
317
318 template <class T>
319 bool EventHandler<T>::_Lock(const char *__file__, unsigned int __line__) 
320 {
321   return eventlock->_Lock(__file__, __line__);
322 }
323 template <class T>
324 bool EventHandler<T>::_Unlock(const char *__file__, unsigned int __line__) 
325 {
326   return eventlock->_Unlock(__file__, __line__);
327 }
328 template <class T>
329 bool EventHandler<T>::_WaitForSignal(const char *__file__, unsigned int __line__) 
330 {
331   return eventlock->_WaitForSignal(__file__, __line__);
332 }
333 template <class T>
334 bool EventHandler<T>::_Broadcast(const char *__file__, unsigned int __line__) 
335 {
336   return eventlock->_Broadcast(__file__, __line__);
337 }
338
339 //bool EventHandler::waitNextEvent(EventRecord &ev)
340 //bool EventHandler::handleEvent(EventRecord &ev)
341 template <class T>
342 void EventHandler<T>::main()
343 {
344   
345   pdpair<unsigned long, const char *> trec;
346   trec.first = getExecThreadID();
347   trec.second = (const char *) idstr;
348   threadmap.push_back(trec);
349   startup_printf("%s[%d]:  welcome to main() for %s\n", __FILE__, __LINE__, idstr);
350   startup_printf("%s[%d]:  new thread id %lu -- %s\n", __FILE__, __LINE__, trec.first, trec.second);
351   tid = trec.first;
352
353
354   startupLock->_Lock(__FILE__, __LINE__);
355   startup_printf("%s[%d]:  about to do init for %s\n", __FILE__, __LINE__, idstr);
356   if (!initialize_event_handler()) {
357     fprintf(stderr, "%s[%d]: failed to init event handler %s\n", FILE__, __LINE__, 
358             getThreadStr(getExecThreadID())); 
359     _isRunning = false;
360     init_ok = false; 
361     startupLock->_Broadcast(__FILE__, __LINE__);
362     startupLock->_Unlock(__FILE__, __LINE__);
363     return;
364   }
365
366   init_ok = true;;
367   startup_printf("%s[%d]:  init success for %s\n", __FILE__, __LINE__, idstr);
368
369   _isRunning = true;
370   startupLock->_Broadcast(__FILE__, __LINE__);
371   startupLock->_Unlock(__FILE__, __LINE__);
372
373   T ev;
374
375   startup_printf("%s[%d]:  before main loop for %s\n", __FILE__, __LINE__, idstr);
376   while (1) {
377     //fprintf(stderr, "%s[%d]:  %s waiting for an event\n", __FILE__, __LINE__, idstr);
378     if (!this->waitNextEvent(ev)) {
379        fprintf(stderr, "%s[%d][%s]:  waitNextEvent failed \n", __FILE__, __LINE__,getThreadStr(getExecThreadID()));
380        if (!stop_request)
381          continue;
382     }
383     if (stop_request) {
384       signal_printf("%s[%d]:  thread terminating at stop request\n", __FILE__, __LINE__);
385       break;
386     }
387     if (!handleEvent(ev)) {
388        
389       fprintf(stderr, "%s[%d][%s]:  handleEvent() failed\n", __FILE__, __LINE__,  getThreadStr(getExecThreadID()));
390     }
391     if (stop_request) break;
392   }
393  //  remove ourselves from the threadmap before exiting\n"
394   global_mutex->_Lock(FILE__, __LINE__);
395  
396   for (unsigned int i = 0; i < threadmap.size(); ++i) {
397     pdpair<unsigned long, const char *> &trec = threadmap[i];
398     if (trec.first == getExecThreadID()) {
399        signal_printf("%s[%d]:  removing [%lu, %s] from thread map\n", FILE__, __LINE__, trec.first, trec.second);
400        threadmap.erase(i,i);
401        break;
402     }
403     
404   }
405   _isRunning = false;
406   if (global_mutex->depth() != 1) {
407      fprintf(stderr, "%s[%d]:  WARNING:  global_mutex->depth() is %d, leaving thread %s\n",
408              FILE__, __LINE__, global_mutex->depth(),idstr);
409      global_mutex->printLockStack();
410   }
411   global_mutex->_Broadcast(FILE__, __LINE__);
412   global_mutex->_Unlock(FILE__, __LINE__);
413
414   signal_printf("%s[%d][%s]:  InternalThread::main exiting\n", FILE__, __LINE__, idstr);
415 }
416
417 //EventHandler::
418 //EventHandler::
419 //EventHandler::
420 #if !defined (CASE_RETURN_STR)
421 #define CASE_RETURN_STR(x) case x: return #x
422 #endif
423 char *eventType2str(eventType x)
424 {
425   switch(x) {
426   CASE_RETURN_STR(evtUndefined);
427   CASE_RETURN_STR(evtNullEvent);
428   CASE_RETURN_STR(evtAnyEvent);
429   CASE_RETURN_STR(evtNewConnection);
430   CASE_RETURN_STR(evtTimeout);
431   CASE_RETURN_STR(evtSignalled);
432   CASE_RETURN_STR(evtException);
433   CASE_RETURN_STR(evtCritical);
434   CASE_RETURN_STR(evtProcessCreate);
435   CASE_RETURN_STR(evtProcessAttach);
436   CASE_RETURN_STR(evtProcessExit); /* used to have exited normally, or via signal, now in info */
437   CASE_RETURN_STR(evtProcessStop);
438   CASE_RETURN_STR(evtProcessSelfTermination);
439   CASE_RETURN_STR(evtThreadCreate);
440   CASE_RETURN_STR(evtThreadExit);
441   CASE_RETURN_STR(evtThreadContextStart);
442   CASE_RETURN_STR(evtThreadContextStop);
443   CASE_RETURN_STR(evtLoadLibrary);
444   CASE_RETURN_STR(evtUnloadLibrary);
445   CASE_RETURN_STR(evtSyscallEntry);
446   CASE_RETURN_STR(evtSyscallExit);
447   CASE_RETURN_STR(evtSuspended);
448   CASE_RETURN_STR(evtInstPointTrap);
449   CASE_RETURN_STR(evtDebugStep);
450   CASE_RETURN_STR(evtDynamicCall);
451   CASE_RETURN_STR(evtRPCSignal);
452   CASE_RETURN_STR(evtError);
453   CASE_RETURN_STR(evtPreFork);
454   CASE_RETURN_STR(evtPostFork);
455   CASE_RETURN_STR(evtExec);
456   CASE_RETURN_STR(evtOneTimeCode);
457   CASE_RETURN_STR(evtUserEvent);
458   CASE_RETURN_STR(evtShutDown);
459   CASE_RETURN_STR(evtProcessInit);
460   CASE_RETURN_STR(evtProcessLoadedRT);
461   CASE_RETURN_STR(evtProcessInitDone);
462   CASE_RETURN_STR(evtThreadDetect);
463   CASE_RETURN_STR(evtLastEvent);
464   default:
465     fprintf(stderr, "%s[%d]:  unknown event type\n", __FILE__, __LINE__);
466   }
467   return "unknown_event_type";
468 }
469
470
471 //  OK -- these template instantiations probably belong more rightly
472 //  in templates2.C, however, including them here gets around
473 //  multiple definition problems introduced by having both template
474 //  and non-template functions in this file.
475 template class EventHandler<EventRecord>;
476 template class EventHandler<DBIEvent>;