Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / BPatch_asyncEventHandler.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 #include "util.h"
34 #include "BPatch_asyncEventHandler.h"
35 #include "EventHandler.h"
36 #include "mailbox.h"
37 #include "BPatch_libInfo.h"
38 #include "signalhandler.h"
39 #include "signalgenerator.h"
40 #include "mapped_object.h"
41 #include "rpcMgr.h"
42 #include <stdio.h>
43
44 #if defined (os_windows)
45 #include <process.h>
46 #else
47 #include <signal.h>
48 #include <pwd.h>
49 #include <sys/types.h>
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #define ASYNC_SOCKET_PATH_LEN 128
53 #endif
54
55 #include "BPatch.h"
56 #include "BPatch_eventLock.h"
57 #include "mailbox.h"
58 #include "callbacks.h"
59 #include "EventHandler.h"
60 #include "util.h"
61 #include "process.h"
62
63 using namespace Dyninst;
64
65 extern unsigned long primary_thread_id;
66
67 BPatch_asyncEventHandler *global_async_event_handler = NULL;
68 BPatch_asyncEventHandler *getAsync() 
69 {
70   if (!global_async_event_handler) {
71     // BPatch creates and initializes, so just...
72
73     abort();
74   }
75   return global_async_event_handler;
76 }
77
78 void makeThreadDeleteCB(process *p, int index);
79
80 //  A wrapper for pthread_create, or its equivalent.
81
82 inline THREAD_RETURN  asyncHandlerWrapper(void *h)
83 {
84   ((BPatch_asyncEventHandler * )h)->main();
85   DO_THREAD_RETURN;
86 }
87
88 bool BPatch_asyncEventHandler::connectToProcess(process *p)
89 {
90    async_printf("%s[%d][%s]:  enter ConnectToProcess %d\n", 
91          FILE__, __LINE__,getThreadStr(getExecThreadID()), p->getPid());
92
93    //  All we do here is add the process to the list of connected processes
94    //  with a fd equal to -1, indicating the not-yet-connected state.
95    //
96    //  Then remotely execute code in the mutatee to initiate the connection.
97
98    //  make sure that this process is not already known
99
100    for (int i = (int) process_fds.size() -1 ; i >= 0; i--) 
101    {
102       if ((p == process_fds[i].proc) || 
103             (p->getPid() == process_fds[i].proc->getPid()))
104       {
105          //  If it is, delete the old record to prepare for the new one.
106          //  This case can be encountered in the case of multiple process management
107          //  when processes are created and terminated rapidly.
108
109                   //  Do we need to close/disconnect socket here??
110
111          fprintf(stderr,"%s[%d]:  duplicate request to connect to process %d\n",
112                FILE__, __LINE__, p->getPid());
113
114          VECTOR_ERASE(process_fds,i,i);
115          //return false;
116       }
117    } 
118
119    process_record newp;
120
121 #if !defined (os_windows)
122
123    std::string sock_fname;
124
125    PDSOCKET newsock =  setup_socket(p->getPid(), sock_fname);
126
127    if (INVALID_PDSOCKET == newsock)
128    {
129            fprintf(stderr, "%s[%d]:  failed to setup socket for new proc\n", FILE__, __LINE__);
130            return false;
131    }
132
133   async_printf("%s[%d]:  new socket %s\n", FILE__, __LINE__, sock_fname.c_str());
134
135    newp.sock = newsock;
136
137 #endif
138    //  add process to list
139    newp.proc = p;
140    newp.fd = -1;
141
142    process_fds.push_back(newp);
143
144    process *llproc = p;
145    assert(llproc->runtime_lib);
146
147 #if defined (os_windows)
148    //  find the variable to set with the port number to connect to
149    pdvector<int_variable *> res;
150
151    llproc->findVarsByAll("connect_port", res, llproc->runtime_lib->fullName().c_str());
152
153    if (!res.size()) 
154    {
155       fprintf(stderr, "%s[%d]:  cannot find var connect_port in rt lib\n",
156             FILE__, __LINE__);
157       return false;
158    }
159
160    int_variable *portVar = res[0];
161
162    bool result = llproc->writeDataSpace((void *) portVar->getAddress(), 
163          sizeof(listen_port), &listen_port);
164
165    if (!result) 
166    {
167       fprintf(stderr, "%s[%d]:  cannot write var connect_port in rt lib\n",
168             FILE__, __LINE__);
169       return false;
170    }
171 #endif
172
173 #if !defined (os_windows)
174    //  tell async handler to expect a new connection:
175    int buf = p->getPid();
176
177    if (sizeof(int) != write(control_pipe_write, & buf, sizeof(int)))
178    {
179            fprintf(stderr, "%s[%d]:  failed to signal async thread\n", FILE__, __LINE__);
180    }
181
182    //  get mutatee to initiate connection
183
184 #if 1 
185    while (llproc->sh->isActivelyProcessing()) 
186    {
187            inferiorrpc_printf("%s[%d]:  waiting before doing user stop for process %d\n", FILE__,
188                            __LINE__, llproc->getPid());
189            llproc->sh->waitForEvent(evtAnyEvent);
190    }
191
192    if (p->hasExited()) 
193    {
194            fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
195            return false;
196    }
197
198
199    long mutator_pid = getpid();
200    pdvector<AstNodePtr> the_args;
201    the_args.push_back(AstNode::operandNode(AstNode::Constant, (void*)mutator_pid));
202    AstNodePtr dynInit = AstNode::funcCallNode("DYNINSTasyncConnect", the_args);
203    llproc->getRpcMgr()->postRPCtoDo(dynInit,
204                                     true, // Don't update cost
205                                     NULL /*no callback*/,
206                                     NULL, // No user data
207                                     false, // Don't run when done
208                                     true, // Use reserved memory
209                                     NULL, NULL);// No particular thread or LWP
210
211
212    llproc->sh->overrideSyncContinueState(ignoreRequest);
213
214    async_printf("%s[%d]:  about to launch RPC for connect\n", FILE__, __LINE__);
215
216    bool rpcNeedsContinue = false;
217    //bool rpcNeedsContinue = true;
218    llproc->getRpcMgr()->launchRPCs(rpcNeedsContinue,
219                    false); // false: not running
220    assert(rpcNeedsContinue);
221
222    async_printf("%s[%d]:  continued proc to run RPC -- wait for RPCSignal\n", FILE__, __LINE__);
223
224    if (p->hasExited()) 
225    {
226            fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
227            return false;
228    }
229
230    eventType evt = llproc->sh->waitForEvent(evtRPCSignal, llproc, NULL /*lwp*/, statusRPCDone);
231
232    if (p->hasExited()) 
233    {
234            fprintf(stderr, "%s[%d]:  oneTimeCode failing because process is terminated\n", FILE__, __LINE__);
235            return false;
236    }
237
238    if (evt == evtProcessExit)
239    {
240            fprintf(stderr, "%s[%d]:  process terminated during async attachl\n", FILE__, __LINE__);
241            return false;
242    }
243
244    async_printf("%s[%d]:  after waitForEvent(evtRPCSignal\n", FILE__, __LINE__);
245
246    //  is this needed?
247    getMailbox()->executeCallbacks(FILE__, __LINE__);
248 #else
249    BPatch_Vector<BPatch_function *> funcs;
250
251    if (!p->getImage()->findFunction("DYNINSTasyncConnect", funcs)
252          || ! funcs.size() ) 
253    {
254       bpfatal("%s[%d]:  could not find function: DYNINSTasyncConnect\n",
255             FILE__, __LINE__);
256       return false;
257    }
258
259    if (funcs.size() > 1) 
260    {
261       bperr("%s[%d]:  found %d varieties of function: DYNINSTasyncConnect\n",
262             FILE__, __LINE__, funcs.size());
263    }
264
265    BPatch_Vector<BPatch_snippet *> args;
266    long mutator_pid = getpid();
267    args.push_back(new BPatch_constExpr((void*)mutator_pid));
268    BPatch_funcCallExpr connectcall(*funcs[0], args);
269
270    //  Run the connect call as oneTimeCode
271
272    void *expected_result = (void *) 1;
273    if ( p->oneTimeCodeInt(connectcall) != expected_result ) 
274    {
275       bpfatal("%s[%d]:  failed to connect mutatee to async handler\n", 
276             FILE__, __LINE__);
277       return false;
278    }
279
280 #endif
281
282    if (llproc->hasExited()) 
283    {
284            fprintf(stderr, "%s[%d]:  unexpected process exit!\n", FILE__, __LINE__);
285            return false;
286    }
287
288    async_printf("%s[%d]:  got new connection\n", FILE__, __LINE__);
289 #endif
290
291
292    return true;
293 }
294
295
296 bool BPatch_asyncEventHandler::detachFromProcess(process *p)
297 {
298         //  find the fd for this process 
299         //  (reformat process vector while we're at it)
300
301         // We can call this if the process has already exited; it then
302         // just cleans up state without executing any events.
303
304 #if ! defined( cap_async_events )
305         return true;
306 #endif
307
308    async_printf("%s[%d]:  welcome to detachFromProcess\n", FILE__, __LINE__);
309
310         int targetfd = -2;
311         for (unsigned int i = 0; i < process_fds.size(); ++i) 
312         {
313                 if (process_fds[i].proc == p) 
314                 {
315                         //fprintf(stderr, "%s[%d]:  removing process %d\n", FILE__, __LINE__, p->getPid());
316                         targetfd  = process_fds[i].fd;
317                         VECTOR_ERASE(process_fds,i,i);
318                         break;
319                 }
320         } 
321
322
323         if (targetfd == -2) 
324         {
325                 //  if we have no record of this process. must already be detached
326                 //bperr("%s[%d]:  detachFromProcess(%d) could not find process record\n",
327                 //      FILE__, __LINE__, p->getPid());
328                 async_printf("%s[%d]:  detachFromProcess: could not find process\n", FILE__, __LINE__);
329                 return true;
330         }
331
332         //  if we never managed to fully attach, targetfd might still be -1.
333         //  not sure if this could happen, but just return in this case.
334         if (targetfd == -1) return true;
335
336         //  get the mutatee to close the comms file desc.
337
338         //  wake up async handler to adjust set of wait fds:
339         int buf = -1;
340
341 #if !defined(os_windows)
342         async_printf("%s[%d]:  detachFromProcess: signalling async thread\n", FILE__, __LINE__);
343
344         if (sizeof(int) != write(control_pipe_write, & buf, sizeof(int)))
345         {
346                 fprintf(stderr, "%s[%d]:  failed to signal async thread\n", FILE__, __LINE__);
347         }
348 #endif
349
350         if (!mutateeDetach(p)) 
351         {
352                 async_printf("%s[%d]:  detachFromProcess: mutateeDetach failed\n", FILE__, __LINE__);
353                 //bperr("%s[%d]:  detachFromProcess(%d) could not clean up mutatee\n",
354                 //      FILE__, __LINE__, p->getPid());
355         }
356
357         //  close our own file desc for this process.
358         P_close(targetfd);
359
360         return true; // true
361 }
362
363 BPatch_asyncEventHandler::BPatch_asyncEventHandler() :
364    EventHandler<EventRecord>(BPatch_eventLock::getLock(), "ASYNC",false /*create thread*/),
365    monitored_points(addrHash) 
366 {
367    //  prefer to do socket init in the initialize() function so that we can
368    //  return errors.
369 }
370 #if defined(os_windows)
371 static
372    void
373 cleanupSockets( void )
374 {
375    WSACleanup();
376 }
377
378 #endif
379
380 #if !defined (os_windows)
381 char *generate_socket_name(char *buf, int mutator_pid, int mutatee_pid)
382 {
383         uid_t euid = geteuid();
384         struct passwd *passwd_info = getpwuid(euid);
385         assert(passwd_info);
386         snprintf(buf, 128, "%s/dyninstAsync.%s.%d.%d", P_tmpdir, 
387                         passwd_info->pw_name, mutator_pid, mutatee_pid);
388         return buf;
389 }
390 #endif
391
392 #if defined (os_windows)
393 PDSOCKET BPatch_asyncEventHandler::setup_socket(int , std::string &)
394 #else
395 PDSOCKET BPatch_asyncEventHandler::setup_socket(int mutatee_pid, std::string &sock_fname)
396 #endif
397 {
398         PDSOCKET sock = INVALID_PDSOCKET;
399
400 #if defined(os_windows)
401    WSADATA data;
402    bool wsaok = false;
403
404    // request WinSock 2.0
405    if ( WSAStartup( MAKEWORD(2,0), &data ) == 0 )
406    {
407       // verify that the version that was provided is one we can use
408
409       if ( (LOBYTE(data.wVersion) == 2) && (HIBYTE(data.wVersion) == 0) )
410       {
411          wsaok = true;
412       }
413    }
414
415    assert(wsaok);
416
417    //  set up socket to accept connections from mutatees (on demand)
418    sock = P_socket(PF_INET, SOCK_STREAM, 0);
419
420    if (INVALID_PDSOCKET == sock) 
421    {
422       bperr("%s[%d]:  new socket failed, sock = %d, lasterror = %d\n", 
423                           FILE__, __LINE__, (unsigned int) sock, WSAGetLastError());
424       return INVALID_PDSOCKET;
425    }
426
427    struct sockaddr_in saddr;
428   struct in_addr *inadr;
429   struct hostent *hostptr;
430
431   hostptr = gethostbyname("localhost");
432   inadr = (struct in_addr *) ((void*) hostptr->h_addr_list[0]);
433   memset((void*) &saddr, 0, sizeof(saddr));
434   saddr.sin_family = PF_INET;
435   saddr.sin_port = htons(0); // ask system to assign
436   saddr.sin_addr = *inadr;
437   
438   const char *path = "windows-socket";
439 #else
440   //  set up socket to accept connections from mutatees (on demand)
441   sock = P_socket(SOCKET_TYPE, SOCK_STREAM, 0);
442
443   if (INVALID_PDSOCKET == sock) 
444   {
445     bperr("%s[%d]:  new socket failed\n", FILE__, __LINE__);
446     return INVALID_PDSOCKET;
447   }
448
449   char path[ASYNC_SOCKET_PATH_LEN];
450   generate_socket_name(path, getpid(), mutatee_pid);
451   sock_fname = std::string(path);
452
453   struct sockaddr_un saddr;
454   saddr.sun_family = AF_UNIX;
455   strcpy(saddr.sun_path, path);
456
457   //  make sure this file does not exist already.
458   if ( 0 != unlink(path) && (errno != ENOENT)) 
459   {
460      bperr("%s[%d]:  unlink failed [%d: %s]\n", FILE__, __LINE__, errno, 
461             strerror(errno));
462   }
463 #endif
464
465   //  bind socket to port (windows) or temp file in the /tmp dir (unix)
466
467   if (PDSOCKET_ERROR == bind(sock, (struct sockaddr *) &saddr, 
468                              sizeof(saddr))) 
469   { 
470     bperr("%s[%d]:  bind socket to %s failed\n", FILE__, __LINE__, path);
471         return INVALID_PDSOCKET;
472   }
473
474 #if defined(os_windows)
475   //  get the port number that was assigned to us
476   int length = sizeof(saddr);
477   if (PDSOCKET_ERROR == getsockname(sock, (struct sockaddr *) &saddr,
478                                     &length)) 
479   {
480     bperr("%s[%d]:  getsockname failed\n", FILE__, __LINE__);
481         return INVALID_PDSOCKET;
482   }
483
484   listen_port = ntohs (saddr.sin_port);
485 #endif
486
487   // set socket to listen for connections  
488   // (we will explicitly accept in the main event loop)
489
490   if (PDSOCKET_ERROR == listen(sock, 32)) 
491   {  //  this is the number of simultaneous connects we can handle
492     bperr("%s[%d]:  listen to %s failed\n", FILE__, __LINE__, path);
493     return INVALID_PDSOCKET;
494   }
495
496   return sock;
497 }
498
499 bool BPatch_asyncEventHandler::initialize()
500 {
501   //  Finally, create the event handling thread
502 #if defined (os_windows)
503    std::string sock_fname;
504
505    PDSOCKET newsock =  setup_socket(0, sock_fname);
506
507    if (INVALID_PDSOCKET == newsock)
508    {
509            fprintf(stderr, "%s[%d]:  failed to setup socket for new proc\n", FILE__, __LINE__);
510            return false;
511    }
512
513    windows_sock = newsock;
514
515 #else
516         int pipe_desc[2];
517         control_pipe_read = -1;
518         control_pipe_write = -1;
519
520         int res = pipe(pipe_desc);
521
522         if (-1 == res)
523         {
524                 fprintf(stderr, "%s[%d]:  failed to setup control pipe\n", FILE__, __LINE__);
525                 return false;
526         }
527         
528         control_pipe_read = pipe_desc[0];
529         control_pipe_write = pipe_desc[1];
530
531         if ((control_pipe_read == -1) || (control_pipe_write == -1))
532         {
533                 fprintf(stderr, "%s[%d]:  failed to setup control pipe\n", FILE__, __LINE__);
534                 return false;
535         }
536 #endif
537
538   if (!createThread()) 
539   {
540     bperr("%s[%d]:  could not create event handling thread\n", 
541           FILE__, __LINE__);
542     return false;
543   }
544
545
546   startup_printf("%s[%d]:  Created async thread\n", FILE__ , __LINE__);
547   return true;
548 }
549
550 BPatch_asyncEventHandler::~BPatch_asyncEventHandler()
551 {
552   if (isRunning()) 
553     if (!shutDown()) 
554         {
555       bperr("%s[%d]:  shut down async event handler failed\n", FILE__, __LINE__);
556     }
557
558 #if defined (os_windows)
559   WSACleanup();
560 #endif
561 }
562
563 bool BPatch_asyncEventHandler::shutDown()
564 {
565   if (!isRunning()) return true;
566
567 #if defined(os_windows)
568   shutDownFlag = true;
569 #else
570   int killres;
571
572   killres = pthread_kill(handler_thread, 9);
573
574   if (killres) 
575   {
576      fprintf(stderr, "%s[%d]:  pthread_kill: %s[%d]\n", FILE__, __LINE__,
577              strerror(killres), killres);
578      return false;
579   }
580
581   fprintf(stderr, "%s[%d]:  \t\t..... killed.\n", FILE__, __LINE__);
582
583 #endif
584
585   return true;
586 }
587
588 bool BPatch_asyncEventHandler::waitNextEvent(EventRecord &ev)
589 {
590
591         async_printf("%s[%d]:  welcome to waitNextEvent\n", FILE__, __LINE__);
592
593   //  Since this function is part of the main event loop, __most__ of
594   //  it is under lock. This is necessary to protect data in this class
595   //  (process-fd mappings for ex) from race conditions.
596   // 
597   //  The basic lock structure:
598   //     Lock
599   //       do set up for select
600   //     Unlock
601   //     select();
602   // 
603   //     Lock
604   //       analyze results of select
605   //     Unlock
606   //     return
607   __LOCK;
608
609   //  keep a static list of events in case we get several simultaneous
610   //  events from select()...  just in case.
611
612   if (event_queue.size()) 
613   {
614      // we already have one (from last call of this func)
615      //
616      //  this might result in an event reordering, not sure if important
617      //   (since we are removing from the end of the list)
618      //ev = event_queue[event_queue.size() - 1];
619      //event_queue.pop_back();
620      ev = event_queue[0];
621      VECTOR_ERASE(event_queue,0,0);
622      bool found = false;
623      for (unsigned i=0; i<process_fds.size(); i++) 
624      {
625         if (process_fds[i].proc &&
626             process_fds[i].proc->getPid() == ev.proc->getPid()) 
627         {
628            found = true;
629            break;
630         }
631         
632      }
633      if (found) 
634      {
635         __UNLOCK;
636         return true;
637      }
638      event_queue.push_back(ev);
639   }
640
641   int width = 0;
642   fd_set readSet;
643   fd_set errSet;
644
645   FD_ZERO(&readSet);
646   FD_ZERO(&errSet);
647
648   //  start off with a NULL event:
649   ev.type = evtNullEvent;
650
651   cleanUpTerminatedProcs();
652
653 #if defined (os_windows)
654   FD_SET(windows_sock, &readSet);
655   FD_SET(windows_sock, &errSet);
656   if (windows_sock > width)
657       width = windows_sock;
658 #else
659   //  build the set of fds we want to wait on, one fd per process
660   FD_SET(control_pipe_read, &readSet);
661   FD_SET(control_pipe_read, &errSet);
662   if (control_pipe_read > width)
663       width = control_pipe_read;
664 #endif
665
666   for (unsigned int i = 0; i < process_fds.size(); ++i) 
667   {
668     if (process_fds[i].fd == -1) 
669         {
670                 assert(process_fds[i].sock != INVALID_PDSOCKET);
671                 FD_SET(process_fds[i].sock, &readSet);
672                 FD_SET(process_fds[i].sock, &errSet);
673                 if (process_fds[i].sock > width)
674                         width = process_fds[i].sock;
675         }
676         else
677         {
678                 FD_SET(process_fds[i].fd, &readSet);
679                 FD_SET(process_fds[i].fd, &errSet);
680                 if ((unsigned)process_fds[i].fd > (unsigned) width)
681                         width = process_fds[i].fd;
682         }
683   }
684
685   // "width" is computed but ignored on Windows NT, where sockets
686   // are not represented by nice little file descriptors.
687
688   async_printf("%s[%d]:  before select:  width =  %d\n",  FILE__, __LINE__, 
689                   width);
690
691   __UNLOCK;
692
693   ////////////////////////////////////////
694   //  WARNING:  THIS SECTION IS UNLOCKED -- don't access any non local vars here
695   ////////////////////////////////////////
696
697   int result = 0;
698   errno = 0;
699
700   do 
701   {
702     result = P_select(width+1, &readSet, NULL, &errSet, NULL);
703   } 
704   while ((result == -1) && (errno == EINTR));
705
706   __LOCK;
707
708   async_printf("%s[%d]:  after select:  res =  %d -- %s\n",  FILE__, __LINE__, 
709                   result, strerror(errno));
710
711   if (-1 == result) {
712     if (errno == EBADF) {
713       if (!cleanUpTerminatedProcs()) 
714           {
715         //fprintf(stderr, "%s[%d]:  FIXME:  select got EBADF, but no procs "
716         // "terminated\n", FILE__, __LINE__);
717         __UNLOCK;
718         return false;
719       }
720       else 
721           {
722         __UNLOCK;
723         return true;  
724       }
725     }
726
727     async_printf("%s[%d]:  select returned -1: %s\n", FILE__, __LINE__, strerror(errno));
728     bperr("%s[%d]:  select returned -1\n", FILE__, __LINE__);
729     __UNLOCK;
730         return false;
731   }
732
733
734 #if defined(os_windows)
735   if (FD_ISSET(windows_sock, &readSet)) 
736   {
737           struct sockaddr cli_addr;
738           SOCKLEN_T clilen = sizeof(cli_addr);
739
740           int new_fd = P_accept(windows_sock, (struct sockaddr *) &cli_addr, &clilen);
741
742           if (-1 == new_fd) 
743           {
744                   bperr("%s[%d]:  accept failed\n", FILE__, __LINE__);
745                   return false;
746           }
747
748           async_printf("%s[%d]:  about to read new connection\n", FILE__, __LINE__);
749
750           //  do a (blocking) read so that we can get the pid associated with
751           //  this connection.
752           EventRecord pid_ev;
753           readReturnValue_t result = readEvent(new_fd, pid_ev);
754
755           if (result != RRVsuccess) 
756           {
757                   async_printf("%s[%d]:  READ ERROR\n", FILE__, __LINE__);
758                   return false;
759           }
760
761           assert(pid_ev.type == evtNewConnection);
762           ev = pid_ev;
763           async_printf("%s[%d]:  new connection to %d\n",  FILE__, __LINE__,
764                           ev.proc->getPid());
765           ev.what = new_fd;
766
767   }
768
769 #else
770
771   if (FD_ISSET(control_pipe_read, &readSet)) 
772   {
773           //  must have a new process to pay attention to
774           int newpid = 0;
775           readReturnValue_t retval = P_socketRead<int>(control_pipe_read, newpid);
776           if (retval != RRVsuccess) 
777           {
778                   async_printf("%s[%d]:  read failed\n", FILE__, __LINE__);
779                   __UNLOCK;
780           }
781
782           if (newpid == -1) 
783           {
784                   async_printf("%s[%d]:  drop connection request\n",  FILE__, __LINE__, newpid);
785                   //  This case happens when we want to tell the async handler that
786                   //  we removed a fd from the set of fds to listen to
787                   ev.type = evtNullEvent;
788                   ev.proc = NULL;
789                   return true;
790           }
791
792           async_printf("%s[%d]:  new connection to %d\n",  FILE__, __LINE__, newpid);
793           ev.type = evtNewConnection;
794           ev.proc = NULL;
795
796           for (unsigned int i = 0; i < process_fds.size(); ++i) 
797           {
798                   if (process_fds[i].proc->getPid() == newpid)
799                           ev.proc = process_fds[i].proc;
800           }
801
802           if (ev.proc == NULL)
803                   fprintf(stderr, "%s[%d]:  could not find process %d\n", FILE__, __LINE__, newpid);
804   }
805 #endif
806
807   for (unsigned int i = 0; i < process_fds.size(); ++i)
808   {
809           PDSOCKET sock = process_fds[i].sock;
810
811           if (sock == INVALID_PDSOCKET)
812                   continue;
813
814           //  See if we have any new connections (accept):
815           if (FD_ISSET(sock, &readSet)) 
816           {
817
818 #if !defined(os_windows)
819                   char sock_name[256];
820                   generate_socket_name(sock_name, getpid(), process_fds[i].proc->getPid());
821 #endif
822
823                   struct sockaddr cli_addr;
824                   SOCKLEN_T clilen = sizeof(cli_addr);
825
826                   async_printf("%s[%d]:  about to accept new connection\n", FILE__, __LINE__); 
827
828                   int new_fd = P_accept(sock, (struct sockaddr *) &cli_addr, &clilen);
829
830                   if (-1 == new_fd) 
831                   {
832                           bperr("%s[%d]:  accept failed\n", FILE__, __LINE__);
833                           __UNLOCK;
834                           abort();
835                           return false;
836                   }
837
838                   async_printf("%s[%d]:  accepted new connection fd %d\n", FILE__, __LINE__, new_fd); 
839                   process_fds[i].fd = new_fd;
840                   process_fds[i].sock = INVALID_PDSOCKET;
841
842 #if !defined(os_windows)
843                   async_printf("%s[%d]:  unlinking socket %s\n", FILE__, __LINE__, sock_name);
844                   unlink(sock_name);
845 #endif
846
847                   async_printf("%s[%d]:  new connection to %d\n",  FILE__, __LINE__, 
848                                   ev.proc->getPid());
849
850                   ev.what = new_fd;
851                   ev.type = evtNewConnection;
852                   ev.proc = process_fds[i].proc;
853           }
854   }
855
856   ////////////////////////////////////////
857   ////////////////////////////////////////
858   ////////////////////////////////////////
859
860   //__LOCK;
861   //  See if we have any processes reporting events:
862
863   for (unsigned int j = 0; j < process_fds.size(); ++j) 
864   {
865     if (-1 == process_fds[j].fd) continue;
866
867     //  Possible race here, if mutator removes fd from set, but events
868     //  are pending??
869
870     if (!FD_ISSET(process_fds[j].fd, &readSet)) 
871        continue;
872
873     async_printf("%s[%d]:  select got event on fd %d, process = %d\n",  FILE__, __LINE__, 
874                         process_fds[j].fd, process_fds[j].proc->getPid());
875
876     // Read event
877     EventRecord new_ev;
878     
879     readReturnValue_t result = readEvent(process_fds[j].fd, new_ev);
880     if (result != RRVsuccess) 
881         {
882         switch (result) 
883                 {
884         //case RRVillegalProcess:
885         case RRVinsufficientData:
886         case RRVreadError:
887         case RRVerror:
888             async_printf("%s[%d]: READ ERROR readEvent returned error code %d\n",
889                          FILE__, __LINE__, result);
890             continue;
891             break;
892         case RRVnoData:
893             //  This read can fail if the mutatee has exited.  Just note that this
894             //  fd is no longer valid, and keep quiet.
895             //if (process_fds[j].proc->isTerminated()) {
896             async_printf("%s[%d]:  READ ERROR read event failed\n", FILE__, __LINE__);
897             //  remove this process/fd from our vector
898             async_printf("%s[%d]:  readEvent failed due to process termination\n", 
899                          FILE__, __LINE__);
900
901             for (unsigned int k = j+1; k < process_fds.size(); ++k) 
902                         {
903                 process_fds[j] = process_fds[k];
904             }
905
906             process_fds.pop_back();
907             // and decrement counter so we examine this element (j) again
908             j--;
909             continue;
910             break;
911         default:
912             assert(0 && "Illegal value returned by readEvent");
913             break;
914         }
915     }
916
917     if (new_ev.type == evtNullEvent) 
918         {
919        continue;
920     }
921
922     new_ev.what = process_fds[j].fd;
923
924     if (ev.type == evtNullEvent) 
925         {
926        //If ev is unset, then set ev to new_ev
927        ev = new_ev;
928     }
929         else 
930         {
931        // If ev is set, then queue up new_ev as we got more than one.
932        event_queue.push_back(new_ev);
933     }
934   }
935   
936   __UNLOCK;
937   return true;
938 }
939
940 //  threadExitWrapper exists to ensure that callbacks are called before
941 //  the thread is deleted.  Maybe there's a better way....
942
943 void threadDeleteWrapper(BPatch_process *p, BPatch_thread *t)
944 {
945    p->deleteBPThread(t);
946 }
947
948 void threadExitWrapper(BPatch_process *p, BPatch_thread *t, 
949                        pdvector<AsyncThreadEventCallback *> *cbs_ptr)
950 {
951   pdvector<AsyncThreadEventCallback *> &cbs = *cbs_ptr;
952
953   for (unsigned int i = 0; i < cbs.size(); ++i) 
954   {
955       AsyncThreadEventCallback *cb = dynamic_cast<AsyncThreadEventCallback *>(cbs[i]);
956       if (cb)
957           (*cb)(p,t);
958   }
959
960   threadDeleteWrapper(p,t);
961 }
962
963 bool handleThreadCreate(process *p, EventRecord &ev, unsigned index, int lwpid, 
964       dynthread_t tid, unsigned long stack_addr, unsigned long start_pc)
965 {
966    //Create the new BPatch_thread object
967    async_printf("%s[%d]:  before createOrUpdateBPThread: pid = %d, " \
968          "start_pc = %p, addr = %p, tid = %lu, index = %d, " \
969          "lwp = %d\n", 
970          FILE__, __LINE__, ev.proc->getPid(), (void *) start_pc, 
971          (void *) stack_addr, tid, index, lwpid);
972
973    int pid = p->getPid();
974
975    BPatch_process *bpprocess = BPatch::bpatch->getProcessByPid(pid);
976    if (!bpprocess)
977    {
978            fprintf(stderr, "%s[%d]:  ERROR:  cannot find relevant bpatch process\n", FILE__, __LINE__);
979            return false;
980    }
981
982    BPatch_thread *thr = bpprocess->handleThreadCreate(index, lwpid, tid, stack_addr, start_pc);
983
984    if (!thr) 
985    {
986       async_printf("%s[%d]: handleThreadCreate failed!\n", FILE__, __LINE__);
987    }
988    else 
989    {
990       if (thr->getTid() != tid) 
991           {
992          fprintf(stderr, "%s[%d]:  thr->getTid(): %lu, tid %lu\n", 
993                                  FILE__, __LINE__, thr->getTid(), tid);
994       }
995    }
996
997    async_printf("%s[%d]:  leaving handleThreadCreate\n", FILE__, __LINE__);
998
999    return (NULL != thr);
1000 }
1001
1002 #if defined(x86_64_unknown_linux2_4)
1003 bool readDynamicCallInfo (PDSOCKET fd, Address &callsite_addr, Address &func_addr, unsigned  address_width)
1004 #else
1005 bool readDynamicCallInfo (PDSOCKET fd, Address &callsite_addr, Address &func_addr, unsigned  /*address_width*/)
1006 #endif
1007 {
1008    BPatch_dynamicCallRecord call_rec;
1009    readReturnValue_t retval ;
1010    //is the mutatee 32 or 64 bit?
1011 #if defined(x86_64_unknown_linux2_4)
1012    if ( address_width == 4 )
1013    {
1014       BPatch_dynamicCallRecord32 call_rec_32;
1015
1016       retval = P_socketRead<BPatch_dynamicCallRecord32>(fd, call_rec_32);
1017       call_rec.call_site_addr = (void*)call_rec_32.call_site_addr;
1018       call_rec.call_target = (void*)call_rec_32.call_target;
1019    } 
1020    else
1021    {
1022       retval = P_socketRead<BPatch_dynamicCallRecord>(fd, call_rec);
1023    }
1024 #else
1025    retval = P_socketRead<BPatch_dynamicCallRecord>(fd, call_rec);
1026 #endif
1027
1028    if (retval != RRVsuccess) 
1029    {
1030       fprintf(stderr, "%s[%d]:  failed to read dynamic call record\n",
1031             FILE__, __LINE__);
1032       return false;
1033    }
1034
1035    callsite_addr = (Address) call_rec.call_site_addr;
1036    func_addr = (Address) call_rec.call_target;
1037
1038    return true;
1039 }
1040
1041 bool handleDynamicCall(process *llproc,
1042       dictionary_hash<Address, BPatch_point *> &monitored_points,
1043       Address callsite_addr, Address func_addr)
1044 {
1045    //  find the point that triggered this event
1046    int pid = llproc->getPid();
1047
1048    BPatch_process *bpprocess = BPatch::bpatch->getProcessByPid(pid);
1049    if (!bpprocess)
1050    {
1051            fprintf(stderr, "%s[%d]:  ERROR:  cannot find relevant bpatch process\n", FILE__, __LINE__);
1052            return false;
1053    }
1054
1055    if (!monitored_points.defines(callsite_addr)) 
1056    {
1057       fprintf(stderr, "%s[%d]:  could not find point for address %lu\n", 
1058             FILE__, __LINE__, (unsigned long) callsite_addr);
1059       return false;
1060    }
1061
1062    BPatch_point *pt = monitored_points[callsite_addr];
1063
1064    //  found the record(s), now find the function that was called
1065    int_function *f = llproc->findFuncByAddr(func_addr);
1066
1067    if (!f) 
1068    {
1069       fprintf(stderr, "%s[%d]:  failed to find BPatch_function\n",
1070             FILE__, __LINE__);
1071       return false;
1072    }
1073
1074    //  find the BPatch_function...
1075
1076    BPatch_function *bpf = NULL;
1077
1078    if (NULL == (bpf = bpprocess->findOrCreateBPFunc(f, NULL))) 
1079    {
1080       fprintf(stderr, "%s[%d]:  failed to find BPatch_function\n",
1081             FILE__, __LINE__);
1082       return false;
1083    }
1084    
1085    //  issue the callback(s) and we're done:
1086
1087    pdvector<CallbackBase *> cbs;
1088
1089    getCBManager()->dispenseCallbacksMatching(evtDynamicCall, cbs);
1090
1091    for (unsigned int i = 0; i < cbs.size(); ++i) 
1092    {
1093       DynamicCallsiteCallback &cb = * ((DynamicCallsiteCallback *) cbs[i]);
1094       cb(pt, bpf);
1095    }
1096
1097    return true;
1098 }
1099
1100 #if defined(x86_64_unknown_linux2_4)
1101 bool readNewThreadEventInfo(PDSOCKET fd, unsigned long &start_pc, unsigned long &stack_addr, 
1102       unsigned &index, int &lwpid, dynthread_t &tid, unsigned address_width) 
1103 #else
1104 bool readNewThreadEventInfo(PDSOCKET fd, unsigned long &start_pc, unsigned long &stack_addr, 
1105       unsigned &index, int &lwpid, dynthread_t &tid, unsigned ) 
1106 #endif
1107 {
1108    BPatch_newThreadEventRecord call_rec;
1109    readReturnValue_t retval;
1110
1111 #if defined(x86_64_unknown_linux2_4)
1112    //is the mutatee 32 or 64 bit?
1113    if ( address_width == 4)
1114    {   
1115            //32 bit
1116       BPatch_newThreadEventRecord32 call_rec_32;
1117       retval = P_socketRead<BPatch_newThreadEventRecord32>(fd, call_rec_32);
1118
1119       call_rec.ppid=call_rec_32.ppid;
1120       call_rec.tid=(void*)call_rec_32.tid;
1121       call_rec.lwp=call_rec_32.lwp;
1122       call_rec.index=call_rec_32.index;
1123       call_rec.stack_addr=(void*)call_rec_32.stack_addr;
1124       call_rec.start_pc=(void*)call_rec_32.start_pc;
1125    } 
1126    else 
1127    {
1128       retval = P_socketRead<BPatch_newThreadEventRecord>(fd, call_rec);
1129    }
1130 #else
1131    retval = P_socketRead<BPatch_newThreadEventRecord>(fd, call_rec);
1132 #endif
1133
1134    if (retval != RRVsuccess) 
1135    {
1136       fprintf(stderr, "%s[%d]:  failed to read thread event call record\n",
1137             FILE__, __LINE__);
1138       return false;
1139    }
1140
1141    start_pc = (unsigned long) call_rec.start_pc;
1142    stack_addr = (unsigned long) call_rec.stack_addr;
1143    index = (unsigned) call_rec.index;
1144    lwpid = call_rec.lwp;
1145    tid = (dynthread_t) call_rec.tid;
1146    return true;
1147 }
1148
1149 bool handleThreadExit(process *appProc,  unsigned index)
1150 {
1151    int pid = appProc->getPid();
1152
1153    BPatch_process *bpprocess = BPatch::bpatch->getProcessByPid(pid);
1154    if (!bpprocess)
1155    {
1156            fprintf(stderr, "%s[%d]:  ERROR:  cannot find relevant bpatch process\n", FILE__, __LINE__);
1157            return false;
1158    }
1159
1160    BPatch_thread *appThread = bpprocess->getThreadByIndex(index);
1161
1162    if (!appThread) 
1163    {
1164       fprintf(stderr, "%s[%d]:  thread index %d does not exist\n", FILE__, __LINE__, index);
1165       return false;
1166    }
1167
1168    //  this is a bit nasty:  since we need to ensure that the callbacks are 
1169    //  called before the thread is deleted, we use a special callback function,
1170    //  threadExitWrapper, specified above, which guarantees serialization.
1171
1172
1173    pdvector<CallbackBase *> cbs;
1174    pdvector<AsyncThreadEventCallback *> *cbs_copy = new pdvector<AsyncThreadEventCallback *>;
1175    getCBManager()->dispenseCallbacksMatching(evtThreadExit, cbs);
1176
1177    for (unsigned int i = 0; i < cbs.size(); ++i) 
1178    {
1179       BPatch::bpatch->signalNotificationFD();
1180       cbs_copy->push_back((AsyncThreadEventCallback *)cbs[i]); 
1181    }
1182
1183    InternalThreadExitCallback *cb_ptr = new InternalThreadExitCallback(threadExitWrapper);
1184    InternalThreadExitCallback &cb = *cb_ptr;
1185
1186    cb(bpprocess, appThread, cbs_copy); 
1187
1188    return true;
1189 }
1190
1191 bool BPatch_asyncEventHandler::handleEventLocked(EventRecord &ev)
1192 {
1193    //if ((ev.type != evtNewConnection) && (ev.type != evtNullEvent))
1194       async_printf("%s[%d]:  inside handleEvent, got %s\n", 
1195             FILE__, __LINE__, eventType2str(ev.type));
1196
1197    int event_fd = -1;
1198    process *appProc = NULL;
1199    unsigned int j;
1200    //  Go through our process list and find the appropriate record
1201
1202    for (j = 0; j < process_fds.size(); ++j) 
1203    {
1204       if (!process_fds[j].proc) 
1205       {
1206          fprintf(stderr, "%s[%d]:  invalid process record!\n", FILE__, __LINE__);
1207          continue;
1208       }
1209
1210       int process_pid = process_fds[j].proc->getPid();
1211
1212       if (ev.proc && process_pid == ev.proc->getPid()) 
1213       {
1214          event_fd = process_fds[j].fd;
1215          appProc = process_fds[j].proc; 
1216          break;
1217       }
1218    }
1219
1220    if (!appProc) 
1221    {
1222       if (ev.type == evtNullEvent) 
1223                   return true; 
1224
1225       //  This can happen if we received a connect packet before the BPatch_process has
1226       //  been created.  Shove it on the front of the queue.
1227
1228       pdvector<EventRecord> temp;
1229
1230       for (unsigned int i = 0; i < event_queue.size(); ++i) 
1231           {
1232          temp.push_back(event_queue[i]);
1233       }
1234
1235       event_queue.clear();
1236       event_queue.push_back(ev);
1237
1238       for (unsigned int i = 0; i < temp.size(); ++i) 
1239           {
1240          event_queue.push_back(temp[i]);
1241       }
1242
1243       return true;
1244    }
1245
1246    async_printf("%s[%d]:  handling event type %s\n", FILE__, __LINE__,
1247          eventType2str(ev.type));
1248
1249    switch (ev.type) {
1250       case evtNullEvent:
1251          return true;
1252       case evtNewConnection: 
1253          {
1254 #if defined (os_windows)
1255             //  add this fd to the pair.
1256             //  this fd will then be watched by select for new events.
1257
1258             if (event_fd != -1) {
1259                // Can happen if we're execing...
1260                fprintf(stderr, "%s[%d]:  WARNING:  event fd for process %d " \
1261                      "is %d (not -1)\n", FILE__, __LINE__, 
1262                      process_fds[j].proc->getPid(), event_fd);
1263             }         
1264             process_fds[j].fd = ev.what;
1265
1266             async_printf("%s[%d]:  after handling new connection, we have\n", 
1267                   FILE__, __LINE__);
1268             for (unsigned int t = 0; t < process_fds.size(); ++t) {
1269                async_printf("\tpid = %d, fd = %d\n", 
1270                      process_fds[t].proc->getPid(), process_fds[t].fd);
1271             }
1272 #endif
1273             return true;
1274          }
1275
1276       case evtShutDown:
1277          return false;
1278
1279       case evtThreadCreate:
1280       {
1281          //  Read details of new thread from fd 
1282          async_printf("%s[%d]: reading event from fd %d\n",
1283                       FILE__, __LINE__, ev.fd);
1284          
1285          int lock_depth = eventlock->depth();
1286          for (int i = 0; i < lock_depth; i++) {
1287             eventlock->_Unlock(FILE__, __LINE__);
1288          }
1289          
1290          
1291          unsigned long start_pc = (unsigned long) -1;
1292          unsigned long stack_addr = (unsigned long) -1;
1293          unsigned index = (unsigned) -1;
1294          int lwpid = -1;
1295          dynthread_t tid;
1296
1297          if (!readNewThreadEventInfo(ev.fd, start_pc, stack_addr, index, lwpid, tid, appProc->getAddressWidth()) ) {
1298             fprintf(stderr, "%s[%d]:  failed to read thread event call record\n",
1299                     FILE__, __LINE__);
1300             return false;
1301          }
1302          
1303          for (int i = 0; i < lock_depth; i++) {
1304             eventlock->_Lock(FILE__, __LINE__);
1305          }
1306
1307 #if defined(os_linux) && (defined(arch_x86_64) || defined(arch_x86))
1308          unsigned maps_size;
1309          map_entries* entries = getLinuxMaps(appProc->getPid(), maps_size);
1310          if (entries) {
1311             bool found = false;
1312             for (unsigned i=0; i<maps_size; i++) {
1313                if (stack_addr >= entries[i].start && stack_addr < entries[i].end)
1314                {
1315                   stack_addr = entries[i].end;
1316                   found = true;
1317                   break;
1318                }
1319             }
1320             if (!found)
1321                stack_addr = 0x0;
1322             free(entries);
1323          }
1324          else {
1325             stack_addr = 0x0;
1326          }
1327 #endif
1328          
1329          bool ret = handleThreadCreate(appProc, ev, index, lwpid, tid, stack_addr, start_pc);
1330          
1331          async_printf("%s[%d]: signalling event...\n", FILE__, __LINE__);
1332          ev.proc->sh->signalEvent(evtThreadCreate);
1333          async_printf("%s[%d]: done signalling event, returning %d\n", FILE__, __LINE__, ret);
1334          return ret;
1335       }
1336       case evtThreadExit: 
1337          {
1338             BPatch_deleteThreadEventRecord rec;
1339             int lock_depth = eventlock->depth();
1340
1341             for (int i = 0; i < lock_depth; i++) 
1342                         {
1343                eventlock->_Unlock(FILE__, __LINE__);
1344             }
1345
1346             readReturnValue_t retval = P_socketRead<BPatch_deleteThreadEventRecord>(ev.fd, rec);
1347             async_printf("%s[%d]: read event, retval %d\n", FILE__, __LINE__);
1348
1349             for (int i = 0; i < lock_depth; i++) 
1350                         {
1351                eventlock->_Lock(FILE__, __LINE__);
1352             }
1353
1354             if (retval != RRVsuccess) 
1355                         {
1356                fprintf(stderr, "%s[%d]:  failed to read thread event call record\n",
1357                      FILE__, __LINE__);
1358                return false;
1359             }
1360
1361             unsigned index = (unsigned) rec.index;
1362
1363             BPatch::bpatch->mutateeStatusChange = true;
1364
1365             if (!handleThreadExit(appProc, index)) 
1366                         {
1367                fprintf(stderr, "%s[%d]:  failed to handleThreadExit \n",
1368                      FILE__, __LINE__);
1369                return false;
1370             }
1371
1372             ev.proc->sh->signalEvent(evtThreadExit);
1373             return true;
1374          }
1375       case evtDynamicCall:
1376          {
1377                          async_printf("%s[%d]:  got evtDynamicCall\n",  FILE__, __LINE__);
1378             //  Read auxilliary packet with dyn call info
1379
1380             Address callsite_addr = (Address) -1;
1381             Address func_addr = (Address) -1;
1382
1383             int lock_depth = eventlock->depth();
1384             for (int i = 0; i < lock_depth; i++) 
1385                         {
1386                eventlock->_Unlock(FILE__, __LINE__);
1387             }
1388
1389             if (!readDynamicCallInfo(ev.fd, callsite_addr, func_addr, appProc->getAddressWidth())) 
1390                         {
1391                fprintf(stderr, "%s[%d]:  failed to read dynamic call record\n",
1392                      FILE__, __LINE__);
1393                return false;
1394             }
1395
1396             for (int i = 0; i < lock_depth; i++) 
1397                         {
1398                eventlock->_Lock(FILE__, __LINE__);
1399             }
1400
1401             if (!handleDynamicCall(appProc, monitored_points, 
1402                      callsite_addr, func_addr)) 
1403                         {
1404                fprintf(stderr, "%s[%d]:  failed to handleDynamicCall for address %lu\n", 
1405                      FILE__, __LINE__, (unsigned long) callsite_addr);
1406                return false;
1407             }
1408
1409             return true;
1410          }
1411       case evtUserEvent:
1412          {
1413 #if !defined (os_windows)
1414             assert(ev.info > 0);
1415             char *userbuf = new char[ev.info];
1416
1417             int lock_depth = eventlock->depth();
1418             for (int i = 0; i < lock_depth; i++) 
1419                         {
1420                eventlock->_Unlock(FILE__, __LINE__);
1421             }
1422
1423             //  Read auxilliary packet with user specifiedbuffer
1424             readReturnValue_t retval = P_socketRead<char>(ev.what, *userbuf, ev.info);
1425
1426             for (int i = 0; i < lock_depth; i++) 
1427                         {
1428                eventlock->_Lock(FILE__, __LINE__);
1429             }
1430
1431             if (retval != RRVsuccess) 
1432                         {
1433                bperr("%s[%d]:  failed to read user specified data\n",
1434                      FILE__, __LINE__);
1435                delete [] userbuf;
1436                return false;
1437             }
1438
1439             pdvector<CallbackBase *> cbs;
1440             getCBManager()->dispenseCallbacksMatching(evtUserEvent, cbs);
1441
1442             for (unsigned int i = 0; i < cbs.size(); ++i) 
1443                         {
1444                BPatch::bpatch->signalNotificationFD();
1445
1446                            int pid = appProc->getPid();
1447
1448                            BPatch_process *bpprocess = BPatch::bpatch->getProcessByPid(pid);
1449                            if (!bpprocess)
1450                            {
1451                                    fprintf(stderr, "%s[%d]:  ERROR:  cannot find relevant bpatch process\n", FILE__, __LINE__);
1452                                    return false;
1453                            }
1454
1455                UserEventCallback *cb = dynamic_cast<UserEventCallback *>(cbs[i]);
1456                if (cb)
1457                   (*cb)(bpprocess, userbuf, ev.info);
1458             }
1459
1460             delete [] userbuf;
1461 #endif
1462             return true;
1463          } 
1464       default:
1465          bperr("%s[%d]:  request to handle unsupported event: %s\n", 
1466                FILE__, __LINE__, eventType2str(ev.type));
1467          return false;
1468          break;
1469
1470    }
1471    return true;
1472 }
1473
1474 bool BPatch_asyncEventHandler::mutateeDetach(process *p)
1475 {
1476    // The process may have already exited... in this case, do nothing
1477    // but return true. 
1478
1479    if ((p == NULL) ||
1480          (p->status() == exited) ||
1481          (p->status() == detached))
1482       return true;
1483
1484 #if 1
1485
1486    // We have a race condition here... if the process already exited we may have
1487    // destroyed the signal generator.
1488    if (p == NULL) return true;
1489    if (p->sh == NULL) return true;
1490
1491
1492    while (p->sh->isActivelyProcessing()) 
1493    {
1494            async_printf("%s[%d]:  waiting before doing user stop for process %d\n", FILE__,
1495                            __LINE__, p->getPid());
1496            p->sh->waitForEvent(evtAnyEvent);
1497    }
1498
1499    // Check again here...
1500    if (p->sh == NULL) return true;
1501
1502    if (p->hasExited()) 
1503    {
1504            return true;
1505    }
1506
1507
1508    pdvector<AstNodePtr> the_args;
1509    AstNodePtr dynInit = AstNode::funcCallNode("DYNINSTasyncDisconnect", the_args);
1510    p->getRpcMgr()->postRPCtoDo(dynInit,
1511                                true, // Don't update cost
1512                                NULL /*no callback*/,
1513                                NULL, // No user data
1514                                false, // Don't run when done
1515                                true, // Use reserved memory
1516                                NULL, NULL);// No particular thread or LWP
1517
1518
1519    p->sh->overrideSyncContinueState(ignoreRequest);
1520
1521    async_printf("%s[%d]:  about to launch RPC for disconnect\n", FILE__, __LINE__);
1522
1523    bool rpcNeedsContinue = false;
1524    //bool rpcNeedsContinue = true;
1525    p->getRpcMgr()->launchRPCs(rpcNeedsContinue,
1526                    false); // false: not running
1527    assert(rpcNeedsContinue);
1528
1529
1530    async_printf("%s[%d]:  continued proc to run RPC -- wait for RPCSignal\n", FILE__, __LINE__);
1531
1532    if (p->hasExited()) 
1533    {
1534            return true;
1535    }
1536
1537    eventType evt = p->sh->waitForEvent(evtRPCSignal, p, NULL /*lwp*/, statusRPCDone);
1538
1539    if (p->hasExited()) 
1540    {
1541            return true;
1542    }
1543
1544    if (evt == evtProcessExit)
1545    {
1546            return true;
1547    }
1548
1549    async_printf("%s[%d]:  after waitForEvent(evtRPCSignal\n", FILE__, __LINE__);
1550
1551    //  is this needed?
1552    getMailbox()->executeCallbacks(FILE__, __LINE__);
1553 #else
1554    //  find the function that will initiate the disconnection
1555    BPatch_Vector<BPatch_function *> funcs;
1556
1557    if (!p->getImage()->findFunction("DYNINSTasyncDisconnect", funcs)
1558          || ! funcs.size() ) 
1559    {
1560       bpfatal("%s[%d]:  could not find function: DYNINSTasyncDisconnect\n",
1561             FILE__, __LINE__);
1562       return false;
1563    }
1564
1565    if (funcs.size() > 1) 
1566    {
1567       bperr("%s[%d]:  found %d varieties of function: DYNINSTasyncDisconnect\n",
1568             FILE__, __LINE__, funcs.size());
1569    }
1570
1571    //  The (int) argument to this function is our pid
1572
1573    BPatch_Vector<BPatch_snippet *> args;
1574    args.push_back(new BPatch_constExpr(P_getpid()));
1575    BPatch_funcCallExpr disconnectcall(*funcs[0], args);
1576
1577    //  Run the connect call as oneTimeCode
1578
1579    if ( p->oneTimeCodeInt(disconnectcall) != 0 ) 
1580    {
1581       bpfatal("%s[%d]:  failed to disconnect mutatee to async handler\n", 
1582             FILE__, __LINE__);
1583       return false;
1584    }
1585 #endif
1586
1587    return true;
1588 }
1589
1590 bool BPatch_asyncEventHandler::cleanUpTerminatedProcs()
1591 {
1592    bool ret = false;
1593
1594    //  iterate from end of vector in case we need to use erase()
1595
1596    for (int i = (int) process_fds.size() -1; i >= 0; i--) 
1597    {
1598       if (process_fds[i].proc->status() == exited) 
1599           {
1600          //  fprintf(stderr, "%s[%d]:  Process %d has terminated, cleaning up\n", FILE__, __LINE__, process_fds[i].proc->getPid());
1601          VECTOR_ERASE(process_fds,i,i);
1602          ret = true;
1603       }
1604    }
1605    return ret;
1606 }
1607
1608 bool BPatch_asyncEventHandler::cleanupProc(process *p)
1609 {
1610    bool ret = false;
1611
1612    //  iterate from end of vector in case we need to use erase()
1613
1614    for (int i = (int) process_fds.size() -1; i >= 0; i--) 
1615    {
1616       if (process_fds[i].proc == p) 
1617           {
1618          //fprintf(stderr, "%s[%d]: Cleaning up process %d\n", FILE__, __LINE__, process_fds[i].proc->getPid());
1619          VECTOR_ERASE(process_fds,i,i);
1620          ret = true;
1621       }
1622    }
1623
1624    return ret;
1625 }
1626
1627 eventType rt2EventType(rtBPatch_asyncEventType t)
1628 {       
1629    switch(t) {
1630       case rtBPatch_nullEvent: return evtNullEvent;
1631       case rtBPatch_newConnectionEvent: return evtNewConnection;
1632       case rtBPatch_internalShutDownEvent: return evtShutDown;
1633       case rtBPatch_threadCreateEvent: return evtThreadCreate;
1634       case rtBPatch_threadDestroyEvent: return evtThreadExit;
1635       case rtBPatch_dynamicCallEvent: return evtDynamicCall;
1636       case rtBPatch_userEvent: return evtUserEvent;
1637       default:
1638                    fprintf(stderr, "%s[%d], invalid conversion\n", FILE__, __LINE__);
1639    };
1640
1641    return evtUndefined;
1642 }         
1643
1644
1645 readReturnValue_t BPatch_asyncEventHandler::readEvent(PDSOCKET fd, EventRecord &ev)
1646 {
1647    rtBPatch_asyncEventRecord rt_ev;
1648    readReturnValue_t retval = P_socketRead<rtBPatch_asyncEventRecord>(fd, rt_ev);
1649
1650    if (retval != RRVsuccess) 
1651    {
1652       async_printf("%s[%d]:  read failed\n", FILE__, __LINE__);
1653       return retval;
1654    }
1655
1656    ev.proc = process::findProcess(rt_ev.pid);
1657
1658    if (ev.proc == NULL) 
1659    {
1660       // Message failed... I've seen this before when we get garbage
1661       // over the FD (juniper, first runs'll do it) --bernat
1662       async_printf("%s[%d]:  read failed, incorrect pid\n", FILE__, __LINE__);
1663       return RRVerror;
1664       //return REillegalProcess;
1665    }
1666
1667    ev.what = rt_ev.event_fd;
1668    ev.fd = fd;
1669    ev.type = rt2EventType(rt_ev.type);
1670 #if !defined(os_windows)
1671    ev.info = rt_ev.size;
1672 #endif
1673
1674    async_printf("%s[%d]: read event, proc = %d, fd = %d\n", FILE__, __LINE__,
1675          ev.proc->getPid(), ev.fd);
1676
1677    return RRVsuccess;
1678 }
1679
1680 #ifndef CASE_RETURN_STR
1681 #define CASE_RETURN_STR(x) case x: return #x
1682 #endif
1683
1684 const char *asyncEventType2Str(BPatch_asyncEventType ev) 
1685 {
1686    switch(ev) {
1687       CASE_RETURN_STR(BPatch_nullEvent);
1688       CASE_RETURN_STR(BPatch_newConnectionEvent);
1689       CASE_RETURN_STR(BPatch_internalShutDownEvent);
1690       CASE_RETURN_STR(BPatch_threadCreateEvent);
1691           CASE_RETURN_STR(BPatch_threadDestroyEvent);
1692           CASE_RETURN_STR(BPatch_dynamicCallEvent);
1693            default:
1694           return "BadEventType";
1695   }
1696 }
1697
1698 bool BPatch_asyncEventHandler::startupThread()
1699 {
1700   if (!isRunning()) 
1701   {
1702     if (!createThread()) 
1703         {
1704       fprintf(stderr, "%s[%d]:  failed to create thread\n", FILE__, __LINE__);
1705       return false;
1706     }
1707   }
1708
1709   return true;
1710 }
1711
1712 bool BPatch_asyncEventHandler::registerMonitoredPoint(BPatch_point *p)
1713 {
1714   if (monitored_points.defines((Address)p->getAddress())) 
1715   {
1716      //    fprintf(stderr, "%s[%d]:  address %lu already exists in monitored_points hash\n", FILE__, __LINE__, (unsigned long) p->getAddress());
1717     return false;
1718   }
1719
1720   monitored_points[(Address)p->getAddress()] = p;
1721
1722   return true;
1723 }