Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / EventHandler.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32
33 #if defined(__XLC__) || defined(__xlC__)
34 #include "common/h/EventHandler.h"
35 #else
36 #if !defined (os_windows)
37 #pragma implementation "EventHandler.h"
38 #endif
39 #endif
40
41 #include "mailbox.h"
42 #include "BPatch_eventLock.h"
43 #include "util.h"
44 #include "common/h/Vector.h"
45 #include "debuggerinterface.h"
46 #include "process.h"
47 #include "common/h/Dictionary.h"
48
49 using namespace Dyninst;
50
51 eventLock *threadMapLock = NULL;
52
53 dictionary_hash<Address, threadmap_t *> *threadmap;
54
55 void initializeThreadMap() {
56     if (threadMapLock != NULL) return;
57
58     threadMapLock  = new eventLock;
59     threadMapLock->_Lock(FILE__, __LINE__);
60
61     threadmap = new dictionary_hash<Address, threadmap_t *>(addrHash4);
62
63     assert(threadmap->size() == 0);
64     assert(getExecThreadID() == primary_thread_id);
65
66     // Initialization
67     threadmap_t *t = new threadmap_t;
68     t->active = true;
69     t->name = P_strdup("UI");
70 #if defined(os_windows)
71     (*threadmap)[_threadid] = t;
72 #else
73     (*threadmap)[getExecThreadID()] = t;
74 #endif
75
76     threadMapLock->_Unlock(FILE__, __LINE__);
77 }
78
79 const char *defaultThreadName = "INVALID";
80 const char *anyThreadName = "any thread";
81
82 const char *getThreadStr(unsigned long tid)
83 {
84     //fprintf(stderr, "... getThreadStr for 0x%lx\n", tid);
85     initializeThreadMap();
86
87     const char *retval = defaultThreadName;
88   
89     threadMapLock->_Lock(FILE__, __LINE__);
90
91     if (threadmap->defines(tid)) {
92         retval = (*threadmap)[tid]->name;
93     }
94     else if (tid == (unsigned long) -1L)  {
95         retval = anyThreadName;
96     }
97     // Else... could be calling this before the thread is named.
98
99     //fprintf(stderr, "... returning string %s\n", retval);
100     threadMapLock->_Unlock(FILE__, __LINE__);
101     
102     return retval;
103 }
104
105 unsigned long getExecThreadID() 
106 {
107 #if defined (os_windows)
108   return (unsigned long) _threadid;
109 #else
110   return (unsigned long) pthread_self();
111 #endif
112 }
113
114 EventRecord::EventRecord() :
115       proc(NULL), 
116       lwp(NULL), 
117       type(evtUndefined), 
118       what(0),
119       status(NULL_STATUS_INITIALIZER),
120       address(0), 
121       fd(0)
122 {
123 #if defined (os_windows)
124   info.dwDebugEventCode = 0;
125   info.dwProcessId = 0;
126   info.dwThreadId = 0;
127 #else
128   info = 0;
129 #endif
130 }
131
132 char *EventRecord::sprint_event(char *buf)
133  {
134     int pid = -1;
135     if (proc && proc->sh && proc->status() != deleted) pid = proc->getPid();
136     sprintf(buf, "[%s:proc=%d:lwp=%d:what=%d:status=%d:addr=%p:fd=%d]", eventType2str(type),
137             pid, lwp ? lwp->get_lwp_id() : 0, what,
138             (int) status, (void *) address, fd);
139     return buf;
140 }
141
142 bool EventRecord::isTemplateOf(EventRecord &src) 
143 {
144      //  returns true if key non-default member values match src
145      if ((type != src.type) && (type != evtAnyEvent) && (type != evtUndefined)) {
146        return false; 
147      }
148      //  maybe we should compare pid instead of proc ptr??
149      if ((proc != src.proc) && (proc != NULL)) {
150        return false;
151      }
152      //  maybe we should compare lwpid instead of lwp ptr??
153      if ((lwp != src.lwp) && (lwp != NULL)) {
154        return false;
155      }
156      if ((what != src.what) && (what != 0)){
157        return false;
158      }
159      if ((status != src.status) && (status != NULL_STATUS_INITIALIZER)) {
160        return false;
161      }
162 #if 0
163     // dont want to compare info, since this is either the raw status output
164     // from waitpid (or waitForDebugEvent), or the argument from a runtime
165     // library call -- eg the pid of a forked process.
166
167      if ((info != src.info) && (info != NULL_INFO_INITIALIZER)) {
168        return false;
169      }
170 #endif
171      return true;
172 }
173
174 //  A wrapper for pthread_create, or its equivalent.
175
176 inline THREAD_RETURN eventHandlerWrapper(void *h)
177 {
178     thread_printf("%s[%d]:  about to call main() for %s\n", __FILE__, __LINE__, ((EventHandler<EventRecord> *)h)->idstr);
179   ((EventHandler<EventRecord> * )h)->main();
180   DO_THREAD_RETURN;
181 }
182
183 InternalThread::InternalThread(const char *id) :
184   _isRunning(false),
185   tid ((unsigned long ) -1),
186   init_ok(true)
187 {
188   idstr = P_strdup(id);
189 }
190
191 InternalThread::~InternalThread() 
192 {
193   if (isRunning()) {
194     //if (!killThread()) {
195     //   fprintf(stderr, "%s[%d]:  failed to terminate internalThread\n", __FILE__, __LINE__);
196    // }
197   }
198   tid = (unsigned long) -1L;
199   free (idstr);
200 }
201
202 bool InternalThread::createThread()
203 {
204     thread_printf("%s[%d]  welcome to createThread(%s)\n", __FILE__, __LINE__, idstr);
205   if (isRunning()) {
206      fprintf(stderr, "%s[%d]:  WARNING:  cannot create thread '%s'which is already running\n", 
207              __FILE__, __LINE__, idstr);
208      return true;
209   }
210   
211   startupLock = new eventLock();
212   startupLock->_Lock(__FILE__, __LINE__);
213
214 #if defined(os_windows)
215   handler_thread = _beginthread(eventHandlerWrapper, 0, (void *) this);
216   if (-1L == handler_thread) {
217     bperr("%s[%d]:  _beginthread(...) failed\n", __FILE__, __LINE__);
218     return false;
219   }
220 #else  // Unixes
221
222   int err = 0;
223   pthread_attr_t handler_thread_attr;
224
225   err = pthread_attr_init(&handler_thread_attr);
226   if (err) {
227     bperr("%s[%d]:  could not init async handler thread attributes: %s, %d\n",
228           __FILE__, __LINE__, strerror(err), err);
229     return false;
230   }
231
232   err = pthread_attr_setdetachstate(&handler_thread_attr, PTHREAD_CREATE_DETACHED);
233   if (err) {
234     bperr("%s[%d]:  could not set async handler thread attrixibcutes: %s, %d\n",
235           __FILE__, __LINE__, strerror(err), err);
236     return false;
237   }
238
239   try {
240           int n_try = 0;
241 try_again:
242   err = pthread_create(&handler_thread, &handler_thread_attr,
243                        &eventHandlerWrapper, (void *) this);
244   if (err) {
245     bperr("%s[%d]:  could not start async handler thread: %s, %d\n",
246           __FILE__, __LINE__, strerror(err), err);
247     fprintf(stderr,"%s[%d]:  could not start async handler thread: %s, %d\n",
248           __FILE__, __LINE__, strerror(err), err);
249         if (err == EAGAIN)
250         {
251                 struct timeval slp;
252                 slp.tv_sec = 0;
253                 slp.tv_usec = 1000;
254                 select(0, NULL, NULL, NULL, &slp);
255                 n_try++;
256                 if (n_try < 10)
257                         goto try_again;
258                 else
259                 {
260                         fprintf(stderr,"%s[%d]:  FAIL:  giving up on async handler thread: %s, %d\n",
261                                         __FILE__, __LINE__, strerror(err), err);
262                 }
263         }
264         return false;
265   }
266   } catch(...) {
267     assert(0);
268   }
269
270   err = pthread_attr_destroy(&handler_thread_attr);
271   if (err) {
272     bperr("%s[%d]:  could not destroy async handler attr: %s, %d\n",
273           __FILE__, __LINE__, strerror(err), err);
274     return false;
275   }
276 #endif
277
278   while (!_isRunning && (init_ok)) {
279       thread_printf("%s[%d]:  createThread (%s) waiting for thread main to start\n", __FILE__, __LINE__, idstr);
280       startupLock->_WaitForSignal(__FILE__, __LINE__);
281       thread_printf("%s[%d]:  createThread (%s) got signal\n", __FILE__, __LINE__, idstr);
282   }
283   startupLock->_Unlock(__FILE__, __LINE__);
284
285   thread_printf("%s[%d]: createThread returning %d\n", FILE__, __LINE__, init_ok);
286
287   if (!init_ok) {
288     return false;
289   }
290   return true;
291
292 }
293
294 bool InternalThread::killThread()
295 {
296   if (!isRunning()) {
297     fprintf(stderr, "%s[%d]:  request to kill already-stopped thread\n", __FILE__, __LINE__);
298     return true;
299   }
300
301 #if defined(os_windows)
302   fprintf(stderr, "%s[%d]:  cannot kill threads on windows\n", __FILE__, __LINE__);
303   return false;
304 #else
305   int killres;
306   killres = pthread_kill(handler_thread, 9);
307   if (killres) {
308      fprintf(stderr, "%s[%d]:  pthread_kill: %s[%d]\n", __FILE__, __LINE__,
309              strerror(killres), killres);
310      return false;
311   }
312   fprintf(stderr, "%s[%d]:  \t\t..... killed.\n", __FILE__, __LINE__);
313   _isRunning = false;
314 #endif
315   return true; 
316 }
317
318 template <class T>
319 EventHandler<T>::EventHandler(eventLock *_lock, const char *id, bool create) :
320   InternalThread(id),
321   eventlock(_lock),
322   stop_request(false),
323   usage_count(0)
324 {
325     //  presume that event handler is created on the ui thread, so make an entry
326     initializeThreadMap();
327     
328     if (create) 
329         if (!createThread()) {
330             fprintf(stderr, "%s[%d]:  failed to create InternalThread\n", __FILE__, __LINE__);
331         }
332 }
333
334 template <class T>
335 EventHandler<T>::~EventHandler()
336 {
337 }
338
339 template <class T>
340 bool EventHandler<T>::_Lock(const char *__file__, unsigned int __line__) 
341 {
342   return eventlock->_Lock(__file__, __line__);
343 }
344 template <class T>
345 bool EventHandler<T>::_Unlock(const char *__file__, unsigned int __line__) 
346 {
347   return eventlock->_Unlock(__file__, __line__);
348 }
349 template <class T>
350 bool EventHandler<T>::_WaitForSignal(const char *__file__, unsigned int __line__) 
351 {
352   return eventlock->_WaitForSignal(__file__, __line__);
353 }
354 template <class T>
355 bool EventHandler<T>::_Broadcast(const char *__file__, unsigned int __line__) 
356 {
357   return eventlock->_Broadcast(__file__, __line__);
358 }
359
360 template <class T>
361 void EventHandler<T>::main()
362 {
363     MONITOR_ENTRY();
364
365     addToThreadMap();
366
367     thread_printf("%s[%d]:  welcome to main() for %s\n", __FILE__, __LINE__, idstr);
368     thread_printf("%s[%d]:  new thread id %lu -- %s\n", __FILE__, __LINE__, tid, idstr);
369
370     startupLock->_Lock(__FILE__, __LINE__);
371     thread_printf("%s[%d]:  about to do init for %s\n", __FILE__, __LINE__, idstr);
372     if (!initialize_event_handler()) {
373         _isRunning = false;
374         init_ok = false; 
375
376         removeFromThreadMap();
377
378         startupLock->_Broadcast(__FILE__, __LINE__);
379         startupLock->_Unlock(__FILE__, __LINE__);
380         return;
381     }
382     
383     init_ok = true;
384     thread_printf("%s[%d]:  init success for %s\n", __FILE__, __LINE__, idstr);
385     
386     _isRunning = true;
387     startupLock->_Broadcast(__FILE__, __LINE__);
388     startupLock->_Unlock(__FILE__, __LINE__);
389     
390     T ev;
391     
392     thread_printf("%s[%d]:  before main loop for %s\n", __FILE__, __LINE__, idstr);
393     while (1) {
394         if (!this->waitNextEvent(ev)) {
395             fprintf(stderr, "%s[%d][%s]:  waitNextEvent failed \n", __FILE__, __LINE__,getThreadStr(getExecThreadID()));
396             if (!stop_request)
397                 continue;
398         }
399         if (stop_request) {
400             thread_printf("%s[%d]:  thread terminating at stop request\n", __FILE__, __LINE__);
401             break;
402         }
403         if (!handleEvent(ev)) {
404             
405             fprintf(stderr, "%s[%d][%s]:  handleEvent() failed\n", __FILE__, __LINE__,  getThreadStr(getExecThreadID()));
406         }
407         if (stop_request) break;
408     }
409  
410    global_mutex->_Lock(FILE__, __LINE__);
411  
412     removeFromThreadMap();
413     
414     _isRunning = false;
415     if (global_mutex->depth() != 1) {
416         fprintf(stderr, "%s[%d]:  WARNING:  global_mutex->depth() is %d, leaving thread %s\n",
417                 FILE__, __LINE__, global_mutex->depth(),idstr);
418         global_mutex->printLockStack();
419     }
420     assert(global_mutex->depth() == 1);
421     global_mutex->_Broadcast(FILE__, __LINE__);
422     global_mutex->_Unlock(FILE__, __LINE__);
423     
424     thread_printf("%s[%d][%s]:  InternalThread::main exiting\n", FILE__, __LINE__, idstr);
425
426     MONITOR_EXIT();
427 }
428
429 template <class T>
430 void EventHandler<T>::addToThreadMap() 
431 {
432     assert(tid == (unsigned long) -1);
433     assert(threadMapLock != NULL);
434     tid = getExecThreadID();
435
436     threadMapLock->_Lock(FILE__, __LINE__);
437
438     if (threadmap->defines(tid)) {
439         // Can happen if we reuse threads... nuke the old.
440         if ((*threadmap)[tid]->active == true) {
441             // Weird...
442             fprintf(stderr, "Warning: replacing thread %s that's still marked as active\n",
443                     (*threadmap)[tid]->name);
444         }
445
446         assert((*threadmap)[tid]->active == false);
447         // We create a new name when we deactivate - delete it here.
448         free((*threadmap)[tid]->name);
449         threadmap_t *foo = (*threadmap)[tid];
450         threadmap->undef(tid);
451         delete foo;
452     }
453
454     threadmap_t *t = new threadmap_t;
455     t->name = P_strdup(idstr);
456     t->active = true;
457     (*threadmap)[tid] = t;
458     
459     threadMapLock->_Unlock(FILE__, __LINE__);
460 }
461
462 template <class T>
463 void EventHandler<T>::removeFromThreadMap() 
464 {
465     //  remove ourselves from the threadmap before exiting
466     assert(threadMapLock != NULL);
467     threadMapLock->_Lock(FILE__, __LINE__);
468
469     if (threadmap->defines(getExecThreadID())) {
470         (*threadmap)[getExecThreadID()]->active = false;
471
472         // We mark the fact that the thread is deleted by changing out the name.
473         char *oldname = (*threadmap)[getExecThreadID()]->name;
474         assert(oldname);
475         char *newname = (char *)malloc(strlen(oldname) + strlen("-DELETED") + 1);
476         sprintf(newname, "%s-DELETED", oldname);
477         (*threadmap)[getExecThreadID()]->name = newname;
478
479         free(oldname);
480     }
481     
482     threadMapLock->_Unlock(FILE__, __LINE__);
483 }
484
485 template <class T>
486 void EventHandler<T>::setName(char *newIdStr) 
487 {
488     free(idstr);
489     idstr = P_strdup(newIdStr);
490
491     // Update the thread map
492     if (threadmap->defines(getExecThreadID())) {
493         free((*threadmap)[getExecThreadID()]->name);
494         (*threadmap)[getExecThreadID()]->name = P_strdup(idstr);
495     }
496     else {
497         fprintf(stderr, "ERROR: threadMap does not contain name for thread %lu (%s)\n",
498                 getExecThreadID(), idstr);
499     }
500 }
501
502
503 #if !defined (CASE_RETURN_STR)
504 #define CASE_RETURN_STR(x) case x: return #x
505 #endif
506
507 const char *eventType2str(eventType x)
508 {
509   switch(x) {
510   CASE_RETURN_STR(evtUndefined);
511   CASE_RETURN_STR(evtNullEvent);
512   CASE_RETURN_STR(evtIgnore);
513   CASE_RETURN_STR(evtAnyEvent);
514   CASE_RETURN_STR(evtNewConnection);
515   CASE_RETURN_STR(evtTimeout);
516   CASE_RETURN_STR(evtSignalled);
517   CASE_RETURN_STR(evtException);
518   CASE_RETURN_STR(evtCritical);
519   CASE_RETURN_STR(evtProcessCreate);
520   CASE_RETURN_STR(evtProcessAttach);
521   CASE_RETURN_STR(evtProcessExit); /* used to have exited normally, or via signal, now in info */
522   CASE_RETURN_STR(evtProcessStop);
523   CASE_RETURN_STR(evtProcessSelfTermination);
524   CASE_RETURN_STR(evtThreadCreate);
525   CASE_RETURN_STR(evtThreadExit);
526   CASE_RETURN_STR(evtThreadContextStart);
527   CASE_RETURN_STR(evtThreadContextStop);
528   CASE_RETURN_STR(evtLoadLibrary);
529   CASE_RETURN_STR(evtUnloadLibrary);
530   CASE_RETURN_STR(evtSyscallEntry);
531   CASE_RETURN_STR(evtSyscallExit);
532   CASE_RETURN_STR(evtSuspended);
533   CASE_RETURN_STR(evtRequestedStop);
534   CASE_RETURN_STR(evtInstPointTrap);
535   CASE_RETURN_STR(evtDebugStep);
536   CASE_RETURN_STR(evtDynamicCall);
537   CASE_RETURN_STR(evtRPCSignal);
538   CASE_RETURN_STR(evtError);
539   CASE_RETURN_STR(evtPreFork);
540   CASE_RETURN_STR(evtPostFork);
541   CASE_RETURN_STR(evtExec);
542   CASE_RETURN_STR(evtOneTimeCode);
543   CASE_RETURN_STR(evtUserEvent);
544   CASE_RETURN_STR(evtShutDown);
545   CASE_RETURN_STR(evtProcessInit);
546   CASE_RETURN_STR(evtProcessLoadedRT);
547   CASE_RETURN_STR(evtProcessInitDone);
548   CASE_RETURN_STR(evtThreadDetect);
549   CASE_RETURN_STR(evtLastEvent);
550   CASE_RETURN_STR(evtLwpAttach);
551   CASE_RETURN_STR(evtLibcLoaded);
552   CASE_RETURN_STR(evtStopThread);
553   CASE_RETURN_STR(evtSignalHandlerCB);
554   CASE_RETURN_STR(evtLibcTrap);
555   default:
556     fprintf(stderr, "%s[%d]:  unknown event type\n", FILE__, __LINE__);
557   }
558   return "unknown_event_type";
559 }
560
561 template <class T> 
562 void EventHandler<T>::MONITOR_ENTRY() {
563     // These should do something, but I'm concerned about
564     // changing a top-level object. So instead I'm
565     // specializing SignalGeneratorCommon.
566     usage_count++;
567 }
568
569 template <class T>
570 void EventHandler<T>::MONITOR_EXIT() {
571     usage_count--;
572 }
573
574
575 //  OK -- these template instantiations probably belong more rightly
576 //  in templates2.C, however, including them here gets around
577 //  multiple definition problems introduced by having both template
578 //  and non-template functions in this file.
579 template class EventHandler<EventRecord>;
580 template class EventHandler<DBIEvent>;
581