These are the windows fixes that I previously alluded to, combined with
[dyninst.git] / dyninstAPI / src / BPatch_asyncEventHandler.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 #include "util.h"
44 #include "BPatch_asyncEventHandler.h"
45 #include "EventHandler.h"
46 #include "mailbox.h"
47 #include "BPatch_libInfo.h"
48 #include "signalhandler.h"
49 #include "signalgenerator.h"
50 #include "mapped_object.h"
51 #include <stdio.h>
52
53 #if defined (os_windows)
54 #include <process.h>
55 #else
56 #include <signal.h>
57 #include <pwd.h>
58 #include <sys/types.h>
59 //#if defined (os_osf)
60 //typedef unsigned long socklen_t;
61 //#ifndef _XOPEN_SOURCE
62 //#define _XOPEN_SOURCE 500
63 //#else
64 //#undef _XOPEN_SOURCE
65 //#define _XOPEN_SOURCE 500
66 //#endif
67 //#ifndef _XOPEN_SOURCE_EXTENDED
68 //#define _XOPEN_SOURCE_EXTENDED 1
69 //#endif
70 //#define _SOCKADDR_LEN
71 #include <sys/types.h>
72 #include <sys/socket.h>
73 //#endif
74 #endif
75
76 #include "BPatch_eventLock.h"
77 #include "mailbox.h"
78 #include "callbacks.h"
79 #include "EventHandler.h"
80 #include "util.h"
81 #include "process.h"
82
83 using namespace Dyninst;
84
85 extern unsigned long primary_thread_id;
86
87 BPatch_asyncEventHandler *global_async_event_handler = NULL;
88 BPatch_asyncEventHandler *getAsync() 
89 {
90   if (!global_async_event_handler) {
91     // BPatch creates and initializes, so just...
92
93     abort();
94   }
95   return global_async_event_handler;
96 }
97 //extern MUTEX_TYPE global_mutex; // see BPatch_eventLock.h
98 //extern bool mutex_created = false;
99
100 void makeThreadDeleteCB(process *p, int index);
101
102 //  A wrapper for pthread_create, or its equivalent.
103
104 inline THREAD_RETURN  asyncHandlerWrapper(void *h)
105 {
106   ((BPatch_asyncEventHandler * )h)->main();
107   DO_THREAD_RETURN;
108 }
109
110 bool BPatch_asyncEventHandler::connectToProcess(BPatch_process *p)
111 {
112    async_printf("%s[%d][%s]:  enter ConnectToProcess %d\n", 
113          FILE__, __LINE__,getThreadStr(getExecThreadID()), p->getPid());
114    //  All we do here is add the process to the list of connected processes
115    //  with a fd equal to -1, indicating the not-yet-connected state.
116    //
117    //  Then remotely execute code in the mutatee to initiate the connection.
118
119    //  make sure that this process is not already known
120    for (int i = (int) process_fds.size() -1 ; i >= 0; i--) 
121    {
122       if ((p == process_fds[i].process) || 
123             (p->getPid() == process_fds[i].process->getPid()))
124       {
125          //  If it is, delete the old record to prepare for the new one.
126          //  This case can be encountered in the case of multiple process management
127          //  when processes are created and terminated rapidly.
128          //fprintf(stderr,"%s[%d]:  duplicate request to connect to process %d\n",
129          //      FILE__, __LINE__, p->getPid());
130          VECTOR_ERASE(process_fds,i,i);
131          //return false;
132       }
133    } 
134
135    //  add process to list
136    process_record newp;
137    newp.process = p;
138    newp.fd = -1;
139    process_fds.push_back(newp);
140
141    //  get mutatee to initiate connection
142
143    //  find the runtime library module
144 #if defined (os_windows)
145    //  find the variable to set with the port number to connect to
146    process *llproc = p->lowlevel_process();
147    assert(llproc->runtime_lib);
148    pdvector<int_variable *> res;
149    p->llproc->findVarsByAll("connect_port", res, llproc->runtime_lib->fullName().c_str());
150    if (!res.size()) {
151       fprintf(stderr, "%s[%d]:  cannot find var connect_port in rt lib\n",
152             FILE__, __LINE__);
153       return false;
154    }
155    int_variable *portVar = res[0];
156    bool result = llproc->writeDataSpace((void *) portVar->getAddress(), 
157          sizeof(listen_port), &listen_port);
158    if (!result) {
159       fprintf(stderr, "%s[%d]:  cannot write var connect_port in rt lib\n",
160             FILE__, __LINE__);
161       return false;
162    }
163 #endif
164
165    return true;
166 }
167
168 bool BPatch_asyncEventHandler::detachFromProcess(BPatch_process *p)
169 {
170    //  find the fd for this process 
171    //  (reformat process vector while we're at it)
172
173    // We can call this if the process has already exited; it then
174    // just cleans up state without executing any events.
175
176 #if ! defined( cap_async_events )
177    return true;
178 #endif
179    int targetfd = -2;
180    for (unsigned int i = 0; i < process_fds.size(); ++i) {
181       if (process_fds[i].process == p) {
182          //fprintf(stderr, "%s[%d]:  removing process %d\n", FILE__, __LINE__, p->getPid());
183          targetfd  = process_fds[i].fd;
184          VECTOR_ERASE(process_fds,i,i);
185          break;
186       }
187    } 
188
189    if (targetfd == -2) {
190       //  if we have no record of this process. must already be detached
191       //bperr("%s[%d]:  detachFromProcess(%d) could not find process record\n",
192       //      FILE__, __LINE__, p->getPid());
193       return true;
194    }
195
196    //  if we never managed to fully attach, targetfd might still be -1.
197    //  not sure if this could happen, but just return in this case.
198    if (targetfd == -1) return true;
199
200    //  get the mutatee to close the comms file desc.
201
202    if (!mutateeDetach(p)) {
203       //bperr("%s[%d]:  detachFromProcess(%d) could not clean up mutatee\n",
204       //      FILE__, __LINE__, p->getPid());
205    }
206
207    //  close our own file desc for this process.
208    P_close(targetfd);
209
210    return true; // true
211 }
212
213 BPatch_asyncEventHandler::BPatch_asyncEventHandler() :
214    EventHandler<EventRecord>(BPatch_eventLock::getLock(), "ASYNC",false /*create thread*/),
215    monitored_points(addrHash) 
216 {
217    //  prefer to do socket init in the initialize() function so that we can
218    //  return errors.
219 }
220 #if defined(os_windows)
221 static
222    void
223 cleanupSockets( void )
224 {
225    WSACleanup();
226 }
227 #else
228
229 #define ASYNC_SOCKET_PATH_LEN 128
230 char path_to_unlink[ASYNC_SOCKET_PATH_LEN];
231 pid_t mutator_pid;
232 void unlink_async_socket()
233 {
234    // work around grandchild forking mechanism used by the testsuite for 
235    // attach. without this check, the async socket will be deleted when the 
236    // child exits immediately after forking the mutatee (grandchild)
237    pid_t curr_pid = getpid();
238    if(curr_pid == mutator_pid)
239       unlink(path_to_unlink);
240 }
241 #endif
242
243 bool BPatch_asyncEventHandler::initialize()
244 {
245
246 #if defined(os_windows)
247    WSADATA data;
248    bool wsaok = false;
249
250    // request WinSock 2.0
251    if( WSAStartup( MAKEWORD(2,0), &data ) == 0 )
252    {
253       // verify that the version that was provided is one we can use
254       if( (LOBYTE(data.wVersion) == 2) && (HIBYTE(data.wVersion) == 0) )
255       {
256          wsaok = true;
257       }
258    }
259    assert(wsaok);
260
261    //  set up socket to accept connections from mutatees (on demand)
262    sock = P_socket(PF_INET, SOCK_STREAM, 0);
263    if (INVALID_PDSOCKET == sock) {
264       bperr("%s[%d]:  new socket failed, sock = %d, lasterror = %d\n", FILE__, __LINE__, (unsigned int) sock, WSAGetLastError());
265       return false;
266    }
267
268    struct sockaddr_in saddr;
269   struct in_addr *inadr;
270   struct hostent *hostptr;
271
272   hostptr = gethostbyname("localhost");
273   inadr = (struct in_addr *) ((void*) hostptr->h_addr_list[0]);
274   memset((void*) &saddr, 0, sizeof(saddr));
275   saddr.sin_family = PF_INET;
276   saddr.sin_port = htons(0); // ask system to assign
277   saddr.sin_addr = *inadr;
278   
279   const char *path = "windows-socket";
280 #else
281   //  set up socket to accept connections from mutatees (on demand)
282   sock = P_socket(SOCKET_TYPE, SOCK_STREAM, 0);
283   if (INVALID_PDSOCKET == sock) {
284     bperr("%s[%d]:  new socket failed\n", FILE__, __LINE__);
285     return false;
286   }
287
288   uid_t euid = geteuid();
289   struct passwd *passwd_info = getpwuid(euid);
290   assert(passwd_info);
291   char path[ASYNC_SOCKET_PATH_LEN];
292   snprintf(path, 128, "%s/dyninstAsync.%s.%d", P_tmpdir, 
293                  passwd_info->pw_name, (int) getpid());
294   strcpy(path_to_unlink, path);
295   mutator_pid = getpid();
296   atexit(unlink_async_socket);
297
298   struct sockaddr_un saddr;
299   saddr.sun_family = AF_UNIX;
300   strcpy(saddr.sun_path, path);
301
302   //  make sure this file does not exist already.
303   if ( 0 != unlink(path) && (errno != ENOENT)) {
304      bperr("%s[%d]:  unlink failed [%d: %s]\n", FILE__, __LINE__, errno, 
305             strerror(errno));
306   }
307 #endif
308
309   //  bind socket to port (windows) or temp file in the /tmp dir (unix)
310
311   if (PDSOCKET_ERROR == bind(sock, (struct sockaddr *) &saddr, 
312                              sizeof(saddr))) { 
313     bperr("%s[%d]:  bind socket to %s failed\n", FILE__, __LINE__, path);
314     return false;
315   }
316
317 #if defined(os_windows)
318   //  get the port number that was assigned to us
319   int length = sizeof(saddr);
320   if (PDSOCKET_ERROR == getsockname(sock, (struct sockaddr *) &saddr,
321                                     &length)) {
322     bperr("%s[%d]:  getsockname failed\n", FILE__, __LINE__);
323     return false;
324   }
325   listen_port = ntohs (saddr.sin_port);
326 #endif
327
328   // set socket to listen for connections  
329   // (we will explicitly accept in the main event loop)
330
331   if (PDSOCKET_ERROR == listen(sock, 32)) {  //  this is the number of simultaneous connects we can handle
332     bperr("%s[%d]:  listen to %s failed\n", FILE__, __LINE__, path);
333     return false;
334   }
335
336   //  Finally, create the event handling thread
337   if (!createThread()) {
338     bperr("%s[%d]:  could not create event handling thread\n", 
339           FILE__, __LINE__);
340     return false;
341   }
342
343
344   startup_printf("%s[%d]:  Created async thread\n", FILE__ , __LINE__);
345   return true;
346 }
347
348 BPatch_asyncEventHandler::~BPatch_asyncEventHandler()
349 {
350   if (isRunning()) 
351     if (!shutDown()) {
352       bperr("%s[%d]:  shut down async event handler failed\n", FILE__, __LINE__);
353     }
354
355 #if defined (os_windows)
356   WSACleanup();
357 #else
358   unlink_async_socket();
359 #endif
360 }
361
362 bool BPatch_asyncEventHandler::shutDown()
363 {
364   if (!isRunning()) goto close_comms;
365
366 #if defined(os_windows)
367   shutDownFlag = true;
368 #else
369   int killres;
370   killres = pthread_kill(handler_thread, 9);
371   if (killres) {
372      fprintf(stderr, "%s[%d]:  pthread_kill: %s[%d]\n", FILE__, __LINE__,
373              strerror(killres), killres);
374      return false;
375   }
376   fprintf(stderr, "%s[%d]:  \t\t..... killed.\n", FILE__, __LINE__);
377 #endif
378
379   close_comms:
380
381   return true;
382 }
383
384 bool BPatch_asyncEventHandler::waitNextEvent(EventRecord &ev)
385 {
386   //  Since this function is part of the main event loop, __most__ of
387   //  it is under lock. This is necessary to protect data in this class
388   //  (process-fd mappings for ex) from race conditions.
389   // 
390   //  The basic lock structure:
391   //     Lock
392   //       do set up for select
393   //     Unlock
394   //     select();
395   // 
396   //     Lock
397   //       analyze results of select
398   //     Unlock
399   //     return
400   __LOCK;
401
402 #if 0
403   async_printf("%s[%d]: welcome to waitnextEvent\n", FILE__, __LINE__);
404 #endif
405   //  keep a static list of events in case we get several simultaneous
406   //  events from select()...  just in case.
407
408   if (event_queue.size()) {
409     // we already have one (from last call of this func)
410     //
411     //  this might result in an event reordering, not sure if important
412     //   (since we are removing from the end of the list)
413     //ev = event_queue[event_queue.size() - 1];
414     //event_queue.pop_back();
415     ev = event_queue[0];
416     VECTOR_ERASE(event_queue,0,0);
417     bool found = false;
418     for (unsigned i=0; i<process_fds.size(); i++) {
419        if (process_fds[i].process &&
420            process_fds[i].process->getPid() == ev.proc->getPid()) 
421        {
422           found = true;
423           break;
424        }
425        
426     }
427     if (found) {
428        __UNLOCK;
429        return true;
430     }
431     event_queue.push_back(ev);
432   }
433
434   int width = 0;
435   fd_set readSet;
436   fd_set errSet;
437
438   FD_ZERO(&readSet);
439   FD_ZERO(&errSet);
440
441   //  start off with a NULL event:
442   ev.type = evtNullEvent;
443
444   cleanUpTerminatedProcs();
445
446   //  build the set of fds we want to wait on, one fd per process
447   for (unsigned int i = 0; i < process_fds.size(); ++i) {
448
449     if (process_fds[i].fd == -1) continue; // waiting for connect/accept
450
451     FD_SET(process_fds[i].fd, &readSet);
452     FD_SET(process_fds[i].fd, &errSet);
453     if (process_fds[i].fd > width)
454       width = process_fds[i].fd;
455   }
456
457   //  Add the (listening) socket to set(s)
458   FD_SET(sock, &readSet);
459   if ((int) sock > width)
460      width = sock;
461
462   // "width" is computed but ignored on Windows NT, where sockets
463   // are not represented by nice little file descriptors.
464
465   __UNLOCK;
466
467   int result = 0;
468   do {
469     result = P_select(width+1, &readSet, NULL, &errSet, NULL);
470   } while ((result == -1) && (errno == EINTR));
471
472   __LOCK;
473
474   if (-1 == result) {
475     if (errno == EBADF) {
476       if (!cleanUpTerminatedProcs()) {
477         //fprintf(stderr, "%s[%d]:  FIXME:  select got EBADF, but no procs "
478         // "terminated\n", FILE__, __LINE__);
479         __UNLOCK;
480         return false;
481       }
482       else {
483         __UNLOCK;
484         return true;  
485       }
486     }
487     bperr("%s[%d]:  select returned -1\n", FILE__, __LINE__);
488     __UNLOCK;
489     return false;
490   }
491
492   ////////////////////////////////////////
493   //  WARNING:  THIS SECTION IS UNLOCKED -- don't access any non local vars here
494   ////////////////////////////////////////
495
496   //  See if we have any new connections (accept):
497   if (FD_ISSET(sock, &readSet)) {
498
499      struct sockaddr cli_addr;
500      SOCKLEN_T clilen = sizeof(cli_addr);
501      
502      int new_fd = P_accept(sock, (struct sockaddr *) &cli_addr, &clilen);
503      if (-1 == new_fd) {
504        bperr("%s[%d]:  accept failed\n", FILE__, __LINE__);
505        return false;
506      }
507      
508      async_printf("%s[%d]:  about to read new connection\n", FILE__, __LINE__); 
509
510      //  do a (blocking) read so that we can get the pid associated with
511      //  this connection.
512      EventRecord pid_ev;
513      readReturnValue_t result = readEvent(new_fd, pid_ev);
514      if (result != RRVsuccess) {
515          async_printf("%s[%d]:  READ ERROR\n", FILE__, __LINE__);
516          return false;
517      }
518      assert(pid_ev.type == evtNewConnection);
519      ev = pid_ev;
520      async_printf("%s[%d]:  new connection to %d\n",  FILE__, __LINE__, 
521                   ev.proc->getPid());
522      ev.what = new_fd;
523   }
524
525   ////////////////////////////////////////
526   ////////////////////////////////////////
527   ////////////////////////////////////////
528
529   //__LOCK;
530   //  See if we have any processes reporting events:
531
532   for (unsigned int j = 0; j < process_fds.size(); ++j) 
533   {
534     if (-1 == process_fds[j].fd) continue;
535
536     //  Possible race here, if mutator removes fd from set, but events
537     //  are pending??
538
539     if (!FD_ISSET(process_fds[j].fd, &readSet)) 
540        continue;
541
542     // Read event
543     EventRecord new_ev;
544     
545     readReturnValue_t result = readEvent(process_fds[j].fd, new_ev);
546     if (result != RRVsuccess) {
547         switch(result) {
548         //case RRVillegalProcess:
549         case RRVinsufficientData:
550         case RRVreadError:
551         case RRVerror:
552             async_printf("%s[%d]: READ ERROR readEvent returned error code %d\n",
553                          FILE__, __LINE__, result);
554             continue;
555             break;
556         case RRVnoData:
557             //  This read can fail if the mutatee has exited.  Just note that this
558             //  fd is no longer valid, and keep quiet.
559             //if (process_fds[j].process->isTerminated()) {
560             async_printf("%s[%d]:  READ ERROR read event failed\n", FILE__, __LINE__);
561             //  remove this process/fd from our vector
562             async_printf("%s[%d]:  readEvent failed due to process termination\n", 
563                          FILE__, __LINE__);
564             for (unsigned int k = j+1; k < process_fds.size(); ++k) {
565                 process_fds[j] = process_fds[k];
566             }
567             process_fds.pop_back();
568             // and decrement counter so we examine this element (j) again
569             j--;
570             continue;
571             break;
572         default:
573             assert(0 && "Illegal value returned by readEvent");
574             break;
575         }
576     }
577     if (new_ev.type == evtNullEvent) {
578        continue;
579     }
580
581     new_ev.what = process_fds[j].fd;
582     if (ev.type == evtNullEvent) {
583        //If ev is unset, then set ev to new_ev
584        ev = new_ev;
585     }
586     else {
587        // If ev is set, then queue up new_ev as we got more than one.
588        event_queue.push_back(new_ev);
589     }
590   }
591 #if 0
592   async_printf("%s[%d]: leaving waitnextEvent\n",  FILE__, __LINE__);
593 #endif
594   
595   __UNLOCK;
596   return true;
597 }
598
599 //  threadExitWrapper exists to ensure that callbacks are called before
600 //  the thread is deleted.  Maybe there's a better way....
601
602 void threadDeleteWrapper(BPatch_process *p, BPatch_thread *t)
603 {
604    p->deleteBPThread(t);
605 }
606
607 void threadExitWrapper(BPatch_process *p, BPatch_thread *t, 
608                        pdvector<AsyncThreadEventCallback *> *cbs_ptr)
609 {
610
611   pdvector<AsyncThreadEventCallback *> &cbs = *cbs_ptr;
612   for (unsigned int i = 0; i < cbs.size(); ++i) {
613       AsyncThreadEventCallback *cb = dynamic_cast<AsyncThreadEventCallback *>(cbs[i]);
614       if (cb)
615           (*cb)(p,t);
616   }
617   threadDeleteWrapper(p,t);
618 }
619
620 bool handleThreadCreate(BPatch_process *p, EventRecord &ev, unsigned index, int lwpid, dynthread_t tid, unsigned long stack_addr, unsigned long start_pc)
621 {
622    bool thread_exists = (p->getThread(tid) != NULL);
623
624    //Create the new BPatch_thread object
625    async_printf("%s[%d]:  before createOrUpdateBPThread: pid = %d, " \
626          "start_pc = %p, addr = %p, tid = %lu, index = %d, " \
627          "lwp = %d\n", 
628          FILE__, __LINE__, ev.proc->getPid(), (void *) start_pc, 
629          (void *) stack_addr, tid, index, lwpid);
630
631    BPatch_thread *thr = p->handleThreadCreate(index, lwpid, tid, stack_addr, start_pc);
632    if (!thr) {
633       async_printf("%s[%d]: handleThreadCreate failed!\n", FILE__, __LINE__);
634    }
635    else {
636       if (thr->getTid() != tid) {
637          fprintf(stderr, "%s[%d]:  thr->getTid(): %lu, tid %lu\n", FILE__, __LINE__, thr->getTid(), tid);
638       }
639    }
640    return (NULL != thr);
641 }
642
643 bool BPatch_asyncEventHandler::handleEventLocked(EventRecord &ev)
644 {
645    if ((ev.type != evtNewConnection) && (ev.type != evtNullEvent))
646       async_printf("%s[%d]:  inside handleEvent, got %s\n", 
647             FILE__, __LINE__, eventType2str(ev.type));
648
649    int event_fd = -1;
650    BPatch_process *appProc = NULL;
651    unsigned int j;
652    //  Go through our process list and find the appropriate record
653
654    for (j = 0; j < process_fds.size(); ++j) {
655       if (!process_fds[j].process) {
656          fprintf(stderr, "%s[%d]:  invalid process record!\n", FILE__, __LINE__);
657          continue;
658       }
659       int process_pid = process_fds[j].process->getPid();
660       if (process_pid == ev.proc->getPid()) {
661          event_fd = process_fds[j].fd;
662          appProc = process_fds[j].process; 
663          break;
664       }
665    }
666
667    if (!appProc) {
668       if (ev.type == evtNullEvent) return true; 
669       //  This can happen if we received a connect packet before the BPatch_process has
670       //  been created.  Shove it on the front of the queue.
671       pdvector<EventRecord> temp;
672       for (unsigned int i = 0; i < event_queue.size(); ++i) {
673          temp.push_back(event_queue[i]);
674       }
675       event_queue.clear();
676       event_queue.push_back(ev);
677       for (unsigned int i = 0; i < temp.size(); ++i) {
678          event_queue.push_back(temp[i]);
679       }
680
681       return true;
682    }
683
684    async_printf("%s[%d]:  handling event type %s\n", FILE__, __LINE__,
685          eventType2str(ev.type));
686
687    switch(ev.type) {
688       case evtNullEvent:
689          return true;
690       case evtNewConnection: 
691          {
692             //  add this fd to the pair.
693             //  this fd will then be watched by select for new events.
694
695             if (event_fd != -1) {
696                // Can happen if we're execing...
697                fprintf(stderr, "%s[%d]:  WARNING:  event fd for process %d " \
698                      "is %d (not -1)\n", FILE__, __LINE__, 
699                      process_fds[j].process->getPid(), event_fd);
700             }         
701             process_fds[j].fd = ev.what;
702
703             async_printf("%s[%d]:  after handling new connection, we have\n", 
704                   FILE__, __LINE__);
705             for (unsigned int t = 0; t < process_fds.size(); ++t) {
706                async_printf("\tpid = %d, fd = %d\n", 
707                      process_fds[t].process->getPid(), process_fds[t].fd);
708             }
709             return true;
710          }
711
712       case evtShutDown:
713          return false;
714
715       case evtThreadCreate:
716          {
717             //  Read details of new thread from fd 
718             async_printf("%s[%d]: reading event from fd %d\n",
719                   FILE__, __LINE__, ev.fd);
720
721             int lock_depth = eventlock->depth();
722             for (int i = 0; i < lock_depth; i++) {
723                eventlock->_Unlock(FILE__, __LINE__);
724             }
725
726             BPatch_newThreadEventRecord call_rec;
727             readReturnValue_t retval;
728
729 #if defined(x86_64_unknown_linux2_4)
730             //is the mutatee 32 or 64 bit?
731             if ( appProc->getAddressWidth() == 4){//32 bit
732                BPatch_newThreadEventRecord32 call_rec_32;
733                retval = P_socketRead<BPatch_newThreadEventRecord32>(ev.fd, call_rec_32);
734                
735                call_rec.ppid=call_rec_32.ppid;
736                call_rec.tid=(void*)call_rec_32.tid;
737                call_rec.lwp=call_rec_32.lwp;
738                call_rec.index=call_rec_32.index;
739                call_rec.stack_addr=(void*)call_rec_32.stack_addr;
740                call_rec.start_pc=(void*)call_rec_32.start_pc;
741             } else {
742                retval = P_socketRead<BPatch_newThreadEventRecord>(ev.fd, call_rec);
743             }
744 #else
745             retval = P_socketRead<BPatch_newThreadEventRecord>(ev.fd, call_rec);
746 #endif
747
748             async_printf("%s[%d]: read event, retval %d\n", FILE__, __LINE__);
749             for (int i = 0; i < lock_depth; i++) {
750                eventlock->_Lock(FILE__, __LINE__);
751             }
752
753             if (retval != RRVsuccess) {
754                bperr("%s[%d]:  failed to read thread event call record\n",
755                      FILE__, __LINE__);
756                return false;
757             }
758
759             bool ret;
760             unsigned long start_pc = (unsigned long) call_rec.start_pc;
761             unsigned long stack_addr = (unsigned long) call_rec.stack_addr;
762             unsigned index = (unsigned) call_rec.index;
763             int lwpid = call_rec.lwp;
764             dynthread_t tid = (dynthread_t) call_rec.tid;
765             ret = handleThreadCreate(appProc, ev, index, lwpid, tid, stack_addr, start_pc);
766
767             async_printf("%s[%d]: signalling event...\n", FILE__, __LINE__);
768             ev.proc->sh->signalEvent(evtThreadCreate);
769             async_printf("%s[%d]: done signalling event, returning %d\n", FILE__, __LINE__, ret);
770             return ret;
771          }
772       case evtThreadExit: 
773          {
774             BPatch_deleteThreadEventRecord rec;
775             int lock_depth = eventlock->depth();
776             for (int i = 0; i < lock_depth; i++) {
777                eventlock->_Unlock(FILE__, __LINE__);
778             }
779 #if 0
780             asyncReadReturnValue_t retval = readEvent(ev.fd/*fd*/, 
781                   (void *) &rec, 
782                   sizeof(BPatch_deleteThreadEventRecord));
783 #endif
784             readReturnValue_t retval = P_socketRead<BPatch_deleteThreadEventRecord>(ev.fd, rec);
785             async_printf("%s[%d]: read event, retval %d\n", FILE__, __LINE__);
786             for (int i = 0; i < lock_depth; i++) {
787                eventlock->_Lock(FILE__, __LINE__);
788             }
789
790             if (retval != RRVsuccess) {
791                bperr("%s[%d]:  failed to read thread event call record\n",
792                      FILE__, __LINE__);
793                return false;
794             }
795
796             unsigned index = (unsigned) rec.index;
797             BPatch_thread *appThread = appProc->getThreadByIndex(index);
798
799             //  this is a bit nasty:  since we need to ensure that the callbacks are 
800             //  called before the thread is deleted, we use a special callback function,
801             //  threadExitWrapper, specified above, which guarantees serialization.
802
803             BPatch::bpatch->mutateeStatusChange = true;
804
805             pdvector<CallbackBase *> cbs;
806             pdvector<AsyncThreadEventCallback *> *cbs_copy = new pdvector<AsyncThreadEventCallback *>;
807             getCBManager()->dispenseCallbacksMatching(ev.type, cbs);
808             for (unsigned int i = 0; i < cbs.size(); ++i) {
809                BPatch::bpatch->signalNotificationFD();
810                cbs_copy->push_back((AsyncThreadEventCallback *)cbs[i]); 
811             }
812
813             InternalThreadExitCallback *cb_ptr = new InternalThreadExitCallback(threadExitWrapper);
814             InternalThreadExitCallback &cb = *cb_ptr;
815             cb(appProc, appThread, cbs_copy); 
816
817             ev.proc->sh->signalEvent(evtThreadExit);
818             return true;
819          }
820       case evtDynamicCall:
821          {
822             //  Read auxilliary packet with dyn call info
823
824             BPatch_dynamicCallRecord call_rec;
825             readReturnValue_t retval ;
826
827             int lock_depth = eventlock->depth();
828             for (int i = 0; i < lock_depth; i++) {
829                eventlock->_Unlock(FILE__, __LINE__);
830             }
831
832             //is the mutatee 32 or 64 bit?
833 #if defined(x86_64_unknown_linux2_4)
834             if( appProc->getAddressWidth() == 4 ){
835                BPatch_dynamicCallRecord32 call_rec_32;
836
837 #if 0
838                retval = readEvent(ev.fd/*fd*/, 
839                      (void *) &call_rec_32, 
840                      sizeof(BPatch_dynamicCallRecord32));
841 #endif
842                retval = P_socketRead<BPatch_dynamicCallRecord32>(ev.fd, call_rec_32);
843                call_rec.call_site_addr = (void*)call_rec_32.call_site_addr;
844                call_rec.call_target = (void*)call_rec_32.call_target;
845             }else
846 #endif
847 #if 0
848                retval = readEvent(ev.fd/*fd*/, 
849                      (void *) &call_rec, 
850                      sizeof(BPatch_dynamicCallRecord));
851 #endif
852             retval = P_socketRead<BPatch_dynamicCallRecord>(ev.fd, call_rec);
853             async_printf("%s[%d]: read event, retval %d\n", FILE__, __LINE__);
854             for (int i = 0; i < lock_depth; i++) {
855                eventlock->_Lock(FILE__, __LINE__);
856             }
857
858             if (retval != RRVsuccess) {
859                bperr("%s[%d]:  failed to read dynamic call record\n",
860                      FILE__, __LINE__);
861                return false;
862             }
863
864             Address callsite_addr = (Address) call_rec.call_site_addr;
865             Address func_addr = (Address) call_rec.call_target;
866
867             //  find the point that triggered this event
868             if (!monitored_points.defines((Address)call_rec.call_site_addr)) {
869                fprintf(stderr, "%s[%d]:  could not find point for address %lu\n", 
870                      FILE__, __LINE__, (unsigned long) call_rec.call_site_addr);
871                return false;
872             }
873
874             BPatch_point *pt = monitored_points[(Address)call_rec.call_site_addr];
875
876             //  found the record(s), now find the function that was called
877             int_function *f = appProc->llproc->findFuncByAddr(func_addr);
878             if (!f) {
879                bperr("%s[%d]:  failed to find BPatch_function\n",
880                      FILE__, __LINE__);
881                return false;
882             }
883
884             //  find the BPatch_function...
885
886             if (!appProc->func_map->defines(f)) {
887                bperr("%s[%d]:  failed to find BPatch_function\n",
888                      FILE__, __LINE__);
889                return false;
890             }
891
892             BPatch_function *bpf = appProc->func_map->get(f);
893
894             if (!bpf) {
895                bperr("%s[%d]:  failed to find BPatch_function\n",
896                      FILE__, __LINE__);
897                return false;
898             }
899
900             //  issue the callback(s) and we're done:
901
902             pdvector<CallbackBase *> cbs;
903             getCBManager()->dispenseCallbacksMatching(evtDynamicCall, cbs);
904             for (unsigned int i = 0; i < cbs.size(); ++i) {
905                DynamicCallsiteCallback &cb = * ((DynamicCallsiteCallback *) cbs[i]);
906                cb(pt, bpf);
907             }
908
909             return true;
910          }
911       case evtUserEvent:
912          {
913 #if !defined (os_windows)
914             assert(ev.info > 0);
915             char *userbuf = new char[ev.info];
916
917             int lock_depth = eventlock->depth();
918             for (int i = 0; i < lock_depth; i++) {
919                eventlock->_Unlock(FILE__, __LINE__);
920             }
921             //  Read auxilliary packet with user specifiedbuffer
922 #if 0
923             asyncReadReturnValue_t retval = readEvent(ev.what, (void *) userbuf, ev.info);
924 #endif
925             readReturnValue_t retval = P_socketRead<char>(ev.what, *userbuf, ev.info);
926             for (int i = 0; i < lock_depth; i++) {
927                eventlock->_Lock(FILE__, __LINE__);
928             }
929             if (retval != RRVsuccess) {
930                bperr("%s[%d]:  failed to read user specified data\n",
931                      FILE__, __LINE__);
932                delete [] userbuf;
933                return false;
934             }
935
936             pdvector<CallbackBase *> cbs;
937             getCBManager()->dispenseCallbacksMatching(evtUserEvent, cbs);
938             for (unsigned int i = 0; i < cbs.size(); ++i) {
939                BPatch::bpatch->signalNotificationFD();
940
941                UserEventCallback *cb = dynamic_cast<UserEventCallback *>(cbs[i]);
942                if (cb)
943                   (*cb)(appProc, userbuf, ev.info);
944             }
945
946             delete [] userbuf;
947 #endif
948             return true;
949          } 
950       default:
951          bperr("%s[%d]:  request to handle unsupported event: %s\n", 
952                FILE__, __LINE__, eventType2str(ev.type));
953          return false;
954          break;
955
956    }
957    return true;
958 }
959
960 bool BPatch_asyncEventHandler::mutateeDetach(BPatch_process *p)
961 {
962    // The process may have already exited... in this case, do nothing
963    // but return true. 
964
965    if ((p->llproc == NULL) ||
966          (p->llproc->status() == exited) ||
967          (p->llproc->status() == detached))
968       return true;
969
970    //  find the function that will initiate the disconnection
971    BPatch_Vector<BPatch_function *> funcs;
972    if (!p->getImage()->findFunction("DYNINSTasyncDisconnect", funcs)
973          || ! funcs.size() ) {
974       bpfatal("%s[%d]:  could not find function: DYNINSTasyncDisconnect\n",
975             FILE__, __LINE__);
976       return false;
977    }
978    if (funcs.size() > 1) {
979       bperr("%s[%d]:  found %d varieties of function: DYNINSTasyncDisconnect\n",
980             FILE__, __LINE__, funcs.size());
981    }
982
983    //  The (int) argument to this function is our pid
984    BPatch_Vector<BPatch_snippet *> args;
985    args.push_back(new BPatch_constExpr(getpid()));
986    BPatch_funcCallExpr disconnectcall(*funcs[0], args);
987
988    //  Run the connect call as oneTimeCode
989    if ( p->oneTimeCodeInt(disconnectcall) != 0 ) {
990       bpfatal("%s[%d]:  failed to disconnect mutatee to async handler\n", 
991             FILE__, __LINE__);
992       return false;
993    }
994
995    return true;
996 }
997
998 bool BPatch_asyncEventHandler::cleanUpTerminatedProcs()
999 {
1000    bool ret = false;
1001    //  iterate from end of vector in case we need to use erase()
1002    for (int i = (int) process_fds.size() -1; i >= 0; i--) {
1003       if (process_fds[i].process->llproc->status() == exited) {
1004          //  fprintf(stderr, "%s[%d]:  Process %d has terminated, cleaning up\n", FILE__, __LINE__, process_fds[i].process->getPid());
1005          VECTOR_ERASE(process_fds,i,i);
1006          ret = true;
1007       }
1008    }
1009    return ret;
1010 }
1011
1012 bool BPatch_asyncEventHandler::cleanupProc(BPatch_process *p)
1013 {
1014    bool ret = false;
1015    //  iterate from end of vector in case we need to use erase()
1016    for (int i = (int) process_fds.size() -1; i >= 0; i--) {
1017       if (process_fds[i].process == p) {
1018          //fprintf(stderr, "%s[%d]: Cleaning up process %d\n", FILE__, __LINE__, process_fds[i].process->getPid());
1019          VECTOR_ERASE(process_fds,i,i);
1020          ret = true;
1021       }
1022    }
1023    return ret;
1024 }
1025
1026 eventType rt2EventType(rtBPatch_asyncEventType t)
1027 {       
1028    switch(t) {
1029       case rtBPatch_nullEvent: return evtNullEvent;
1030       case rtBPatch_newConnectionEvent: return evtNewConnection;
1031       case rtBPatch_internalShutDownEvent: return evtShutDown;
1032       case rtBPatch_threadCreateEvent: return evtThreadCreate;
1033       case rtBPatch_threadDestroyEvent: return evtThreadExit;
1034       case rtBPatch_dynamicCallEvent: return evtDynamicCall;
1035       case rtBPatch_userEvent: return evtUserEvent;
1036       default:
1037                                fprintf(stderr, "%s[%d], invalid conversion\n", FILE__, __LINE__);
1038    }
1039    return evtUndefined;
1040 }         
1041
1042
1043 readReturnValue_t BPatch_asyncEventHandler::readEvent(PDSOCKET fd, EventRecord &ev)
1044 {
1045    rtBPatch_asyncEventRecord rt_ev;
1046 #if 0
1047    asyncReadReturnValue_t retval = readEvent(fd, &rt_ev, sizeof(rtBPatch_asyncEventRecord));
1048 #endif
1049    readReturnValue_t retval = P_socketRead<rtBPatch_asyncEventRecord>(fd, rt_ev);
1050    if (retval != RRVsuccess) {
1051       async_printf("%s[%d]:  read failed\n", FILE__, __LINE__);
1052       return retval;
1053    }
1054    ev.proc = process::findProcess(rt_ev.pid);
1055    if (ev.proc == NULL) {
1056       // Message failed... I've seen this before when we get garbage
1057       // over the FD (juniper, first runs'll do it) --bernat
1058       async_printf("%s[%d]:  read failed, incorrect pid\n", FILE__, __LINE__);
1059       return RRVerror;
1060       //return REillegalProcess;
1061    }
1062    ev.what = rt_ev.event_fd;
1063    ev.fd = fd;
1064    ev.type = rt2EventType(rt_ev.type);
1065 #if !defined(os_windows)
1066    ev.info = rt_ev.size;
1067 #endif
1068    async_printf("%s[%d]: read event, proc = %d, fd = %d\n", FILE__, __LINE__,
1069          ev.proc->getPid(), ev.fd);
1070    return RRVsuccess;
1071 }
1072
1073 #if 0
1074 #if !defined(os_windows)
1075 asyncReadReturnValue_t BPatch_asyncEventHandler::readEvent(PDSOCKET fd, void *ev, ssize_t sz)
1076 {
1077    ssize_t bytes_read = 0;
1078 try_again:
1079    bytes_read = read(fd, ev, sz);
1080
1081    if ( (ssize_t)-1 == bytes_read ) {
1082       if (errno == EAGAIN || errno == EINTR) 
1083          goto try_again;
1084
1085       fprintf(stderr, "%s[%d]:  read failed: %s:%d\n", FILE__, __LINE__,
1086             strerror(errno), errno);
1087       return REreadError;
1088    }
1089
1090    if (0 == bytes_read) {
1091       //  fd closed on other end (most likely)
1092       //bperr("%s[%d]:  cannot read, fd is closed\n", FILE__, __LINE__);
1093       return REnoData;
1094    }
1095    if (bytes_read != sz) {
1096       bperr("%s[%d]:  read wrong number of bytes! %d, not %d\n", 
1097             FILE__, __LINE__, bytes_read, sz);
1098       bperr("FIXME:  Need better logic to handle incomplete reads\n");
1099       return REinsufficientData;
1100    }
1101
1102    return REsuccess;
1103 }
1104 #else
1105
1106 asyncReadReturnValue_t BPatch_asyncEventHandler::readEvent(PDSOCKET fd, void *ev, ssize_t sz)
1107 {
1108    ssize_t bytes_read = 0;
1109
1110    bytes_read = recv( fd, (char *)ev, sz, 0 );
1111
1112    if ( PDSOCKET_ERROR == bytes_read && errno != 0 ) {
1113       fprintf(stderr, "%s[%d]:  read failed: %s:%d\n", FILE__, __LINE__,
1114             strerror(errno), errno);
1115       return REreadError;
1116    }
1117
1118    if (0 == bytes_read || (PDSOCKET_ERROR == bytes_read && errno == 0)) {
1119       //  fd closed on other end (most likely)
1120       //bperr("%s[%d]:  cannot read, fd is closed\n", FILE__, __LINE__);
1121       return REnoData;
1122    }
1123
1124    if (bytes_read != sz) {
1125       bperr("%s[%d]:  read wrong number of bytes!\n", FILE__, __LINE__);
1126       bperr("FIXME:  Need better logic to handle incomplete reads\n");
1127       return REinsufficientData;
1128    }
1129
1130    return REsuccess;
1131 }
1132 #endif
1133 #endif
1134
1135
1136 #ifndef CASE_RETURN_STR
1137 #define CASE_RETURN_STR(x) case x: return #x
1138 #endif
1139
1140 const char *asyncEventType2Str(BPatch_asyncEventType ev) {
1141    switch(ev) {
1142       CASE_RETURN_STR(BPatch_nullEvent);
1143       CASE_RETURN_STR(BPatch_newConnectionEvent);
1144       CASE_RETURN_STR(BPatch_internalShutDownEvent);
1145       CASE_RETURN_STR(BPatch_threadCreateEvent);
1146   CASE_RETURN_STR(BPatch_threadDestroyEvent);
1147   CASE_RETURN_STR(BPatch_dynamicCallEvent);
1148   default:
1149   return "BadEventType";
1150   }
1151 }
1152
1153 bool BPatch_asyncEventHandler::startupThread()
1154 {
1155   if (!isRunning()) {
1156     if (!createThread()) {
1157       fprintf(stderr, "%s[%d]:  failed to create thread\n", FILE__, __LINE__);
1158       return false;
1159     }
1160   }
1161   return true;
1162 }
1163
1164 bool BPatch_asyncEventHandler::registerMonitoredPoint(BPatch_point *p)
1165 {
1166   if (monitored_points.defines((Address)p->getAddress())) {
1167      //    fprintf(stderr, "%s[%d]:  address %lu already exists in monitored_points hash\n", FILE__, __LINE__, (unsigned long) p->getAddress());
1168     return false;
1169   }
1170   monitored_points[(Address)p->getAddress()] = p;
1171   return true;
1172 }