eventmachine 0.12.8 → 0.12.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +2 -1
  2. data/Rakefile +155 -45
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +13 -14
  5. data/ext/binder.h +5 -7
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +20 -20
  8. data/ext/ed.cpp +242 -81
  9. data/ext/ed.h +39 -22
  10. data/ext/em.cpp +127 -108
  11. data/ext/em.h +27 -18
  12. data/ext/emwin.cpp +3 -3
  13. data/ext/eventmachine.h +49 -38
  14. data/ext/eventmachine_cpp.h +4 -4
  15. data/ext/extconf.rb +28 -13
  16. data/ext/fastfilereader/extconf.rb +11 -5
  17. data/ext/project.h +12 -1
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +3 -3
  20. data/ext/ssl.h +2 -2
  21. data/java/src/com/rubyeventmachine/EmReactor.java +396 -249
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +16 -4
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +23 -5
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +181 -61
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +25 -31
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +2 -2
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +1 -1
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +2 -2
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +1 -1
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +1 -1
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +1 -0
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +4 -2
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +1 -1
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +1 -0
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +1 -0
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +5 -0
  38. data/lib/em/protocols.rb +1 -0
  39. data/lib/em/protocols/httpclient2.rb +8 -0
  40. data/lib/em/protocols/line_and_text.rb +0 -1
  41. data/lib/em/protocols/linetext2.rb +1 -0
  42. data/lib/em/protocols/object_protocol.rb +8 -2
  43. data/lib/em/protocols/smtpclient.rb +42 -16
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +1 -1
  46. data/lib/em/timers.rb +2 -1
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +124 -9
  50. data/tasks/{cpp.rake → cpp.rake_example} +0 -0
  51. data/tests/test_attach.rb +29 -4
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +10 -20
  54. data/tests/test_epoll.rb +0 -2
  55. data/tests/test_get_sock_opt.rb +30 -0
  56. data/tests/test_httpclient2.rb +3 -3
  57. data/tests/test_inactivity_timeout.rb +21 -1
  58. data/tests/test_ltp.rb +0 -6
  59. data/tests/test_next_tick.rb +0 -2
  60. data/tests/test_pause.rb +70 -0
  61. data/tests/test_pending_connect_timeout.rb +48 -0
  62. data/tests/test_ssl_args.rb +16 -5
  63. data/tests/test_timers.rb +22 -1
  64. metadata +14 -12
  65. data/tasks/project.rake +0 -79
  66. data/tasks/tests.rake +0 -193
data/ext/ed.h CHANGED
@@ -56,11 +56,13 @@ class EventableDescriptor: public Bindable_t
56
56
  bool ShouldDelete();
57
57
  // Do we have any data to write? This is used by ShouldDelete.
58
58
  virtual int GetOutboundDataSize() {return 0;}
59
+ virtual bool IsWatchOnly(){ return false; }
59
60
 
60
- void ScheduleClose (bool after_writing);
61
+ virtual void ScheduleClose (bool after_writing);
61
62
  bool IsCloseScheduled();
63
+ virtual void HandleError(){ ScheduleClose (false); }
62
64
 
63
- void SetEventCallback (void (*cb)(const char*, int, const char*, int));
65
+ void SetEventCallback (void (*cb)(const unsigned long, int, const char*, const unsigned long));
64
66
 
65
67
  virtual bool GetPeername (struct sockaddr*) {return false;}
66
68
  virtual bool GetSockname (struct sockaddr*) {return false;}
@@ -75,13 +77,20 @@ class EventableDescriptor: public Bindable_t
75
77
 
76
78
  virtual float GetCommInactivityTimeout() {return 0.0;}
77
79
  virtual int SetCommInactivityTimeout (float value) {return 0;}
80
+ float GetPendingConnectTimeout();
81
+ int SetPendingConnectTimeout (float value);
78
82
 
79
83
  #ifdef HAVE_EPOLL
80
84
  struct epoll_event *GetEpollEvent() { return &EpollEvent; }
81
85
  #endif
82
86
 
83
- virtual void StartProxy(const char*);
87
+ virtual void StartProxy(const unsigned long, const unsigned long);
84
88
  virtual void StopProxy();
89
+ virtual void SetProxiedFrom(EventableDescriptor*, const unsigned long);
90
+ virtual int SendOutboundData(const char*,int){ return -1; }
91
+ virtual bool IsPaused(){ return false; }
92
+ virtual bool Pause(){ return false; }
93
+ virtual bool Resume(){ return false; }
85
94
 
86
95
  private:
87
96
  bool bCloseNow;
@@ -89,31 +98,24 @@ class EventableDescriptor: public Bindable_t
89
98
 
90
99
  protected:
91
100
  int MySocket;
92
- enum {
93
- // 4 seconds is too short, most other libraries default to OS settings
94
- // which in 2.6 kernel defaults to a 60 second connect timeout.
95
- //
96
- // Curl-Multi: http://curl.haxx.se/mail/lib-2001-01/0019.html
97
- //
98
- // updating to 50 seconds, so we catch it before the OS does
99
-
100
- // can easily be made an instance variable
101
- PendingConnectTimeout = 50000000 // now in usec
102
- };
103
101
 
104
- void (*EventCallback)(const char*, int, const char*, int);
102
+ void (*EventCallback)(const unsigned long, int, const char*, const unsigned long);
105
103
  void _GenericInboundDispatch(const char*, int);
106
104
 
107
105
  Int64 CreatedAt;
108
106
  bool bCallbackUnbind;
109
107
  int UnbindReasonCode;
110
- char *ProxyTarget;
108
+ EventableDescriptor *ProxyTarget;
109
+ EventableDescriptor *ProxiedFrom;
110
+
111
+ unsigned long MaxOutboundBufSize;
111
112
 
112
113
  #ifdef HAVE_EPOLL
113
114
  struct epoll_event EpollEvent;
114
115
  #endif
115
116
 
116
117
  EventMachine_t *MyEventMachine;
118
+ int PendingConnectTimeout;
117
119
  };
118
120
 
119
121
 
@@ -147,16 +149,27 @@ class ConnectionDescriptor: public EventableDescriptor
147
149
  ConnectionDescriptor (int, EventMachine_t*);
148
150
  virtual ~ConnectionDescriptor();
149
151
 
150
- static int SendDataToConnection (const char*, const char*, int);
151
- static void CloseConnection (const char*, bool);
152
- static int ReportErrorStatus (const char*);
152
+ static int SendDataToConnection (const unsigned long, const char*, int);
153
+ static void CloseConnection (const unsigned long, bool);
154
+ static int ReportErrorStatus (const unsigned long);
153
155
 
154
156
  int SendOutboundData (const char*, int);
155
157
 
156
158
  void SetConnectPending (bool f);
159
+ virtual void ScheduleClose (bool after_writing);
160
+ virtual void HandleError();
157
161
 
158
162
  void SetNotifyReadable (bool);
159
163
  void SetNotifyWritable (bool);
164
+ void SetWatchOnly (bool);
165
+
166
+ bool IsPaused(){ return bPaused; }
167
+ bool Pause();
168
+ bool Resume();
169
+
170
+ bool IsNotifyReadable(){ return bNotifyReadable; }
171
+ bool IsNotifyWritable(){ return bNotifyWritable; }
172
+ virtual bool IsWatchOnly(){ return bWatchOnly; }
160
173
 
161
174
  virtual void Read();
162
175
  virtual void Write();
@@ -196,10 +209,12 @@ class ConnectionDescriptor: public EventableDescriptor
196
209
  };
197
210
 
198
211
  protected:
212
+ bool bPaused;
199
213
  bool bConnectPending;
200
214
 
201
215
  bool bNotifyReadable;
202
216
  bool bNotifyWritable;
217
+ bool bWatchOnly;
203
218
 
204
219
  bool bReadAttemptedAfterClose;
205
220
  bool bWriteAttemptedAfterClose;
@@ -215,16 +230,18 @@ class ConnectionDescriptor: public EventableDescriptor
215
230
  bool bSslVerifyPeer;
216
231
  bool bSslPeerAccepted;
217
232
  #endif
218
- bool bIsServer;
219
233
 
220
234
  #ifdef HAVE_KQUEUE
221
235
  bool bGotExtraKqueueEvent;
222
236
  #endif
223
237
 
238
+ bool bIsServer;
224
239
  Int64 LastIo;
225
240
  int InactivityTimeout;
226
241
 
227
242
  private:
243
+ void _UpdateEvents();
244
+ void _UpdateEvents(bool, bool);
228
245
  void _WriteOutboundData();
229
246
  void _DispatchInboundData (const char *buffer, int size);
230
247
  void _DispatchCiphertext();
@@ -264,7 +281,7 @@ class DatagramDescriptor: public EventableDescriptor
264
281
  virtual float GetCommInactivityTimeout();
265
282
  virtual int SetCommInactivityTimeout (float value);
266
283
 
267
- static int SendDatagram (const char*, const char*, int, const char*, int);
284
+ static int SendDatagram (const unsigned long, const char*, int, const char*, int);
268
285
 
269
286
 
270
287
  protected:
@@ -306,7 +323,7 @@ class AcceptorDescriptor: public EventableDescriptor
306
323
 
307
324
  virtual bool GetSockname (struct sockaddr*);
308
325
 
309
- static void StopAcceptor (const char *binding);
326
+ static void StopAcceptor (const unsigned long binding);
310
327
  };
311
328
 
312
329
  /********************
data/ext/em.cpp CHANGED
@@ -37,7 +37,7 @@ unsigned gLastTickCount;
37
37
  /* The numer of max outstanding timers was once a const enum defined in em.h.
38
38
  * Now we define it here so that users can change its value if necessary.
39
39
  */
40
- static int MaxOutstandingTimers = 1000;
40
+ static unsigned int MaxOutstandingTimers = 10000;
41
41
 
42
42
 
43
43
  /* Internal helper to convert strings to internet addresses. IPv6-aware.
@@ -79,17 +79,17 @@ void EventMachine_t::SetMaxTimerCount (int count)
79
79
  EventMachine_t::EventMachine_t
80
80
  ******************************/
81
81
 
82
- EventMachine_t::EventMachine_t (void (*event_callback)(const char*, int, const char*, int)):
82
+ EventMachine_t::EventMachine_t (void (*event_callback)(const unsigned long, int, const char*, const unsigned long)):
83
+ HeartbeatInterval(2000000),
83
84
  EventCallback (event_callback),
84
85
  NextHeartbeatTime (0),
85
86
  LoopBreakerReader (-1),
86
87
  LoopBreakerWriter (-1),
87
88
  bEpoll (false),
89
+ epfd (-1),
88
90
  bKqueue (false),
89
91
  kqfd (-1),
90
- epfd (-1),
91
- inotify (NULL),
92
- HeartbeatInterval(2)
92
+ inotify (NULL)
93
93
  {
94
94
  // Default time-slice is just smaller than one hundred mills.
95
95
  Quantum.tv_sec = 0;
@@ -132,8 +132,10 @@ EventMachine_t::~EventMachine_t()
132
132
  close (LoopBreakerWriter);
133
133
 
134
134
  // Remove any file watch descriptors
135
- for(map<int, Bindable_t*>::iterator f=Files.begin(); f != Files.end(); f++)
135
+ while(!Files.empty()) {
136
+ map<int, Bindable_t*>::iterator f = Files.begin();
136
137
  UnwatchFile (f->first);
138
+ }
137
139
 
138
140
  if (epfd != -1)
139
141
  close (epfd);
@@ -265,7 +267,7 @@ int EventMachine_t::SetRlimitNofile (int nofiles)
265
267
  getrlimit (RLIMIT_NOFILE, &rlim);
266
268
  if (nofiles >= 0) {
267
269
  rlim.rlim_cur = nofiles;
268
- if (nofiles > rlim.rlim_max)
270
+ if ((unsigned int)nofiles > rlim.rlim_max)
269
271
  rlim.rlim_max = nofiles;
270
272
  setrlimit (RLIMIT_NOFILE, &rlim);
271
273
  // ignore the error return, for now at least.
@@ -477,15 +479,17 @@ bool EventMachine_t::_RunEpollOnce()
477
479
  for (int i=0; i < s; i++) {
478
480
  EventableDescriptor *ed = (EventableDescriptor*) epoll_events[i].data.ptr;
479
481
 
480
- if (epoll_events[i].events & (EPOLLERR | EPOLLHUP))
481
- ed->ScheduleClose (false);
482
+ if (ed->IsWatchOnly() && ed->GetSocket() == INVALID_SOCKET)
483
+ continue;
484
+
485
+ assert(ed->GetSocket() != INVALID_SOCKET);
486
+
482
487
  if (epoll_events[i].events & EPOLLIN)
483
488
  ed->Read();
484
- if (epoll_events[i].events & EPOLLOUT) {
489
+ if (epoll_events[i].events & EPOLLOUT)
485
490
  ed->Write();
486
- epoll_ctl (epfd, EPOLL_CTL_MOD, ed->GetSocket(), ed->GetEpollEvent());
487
- // Ignoring return value
488
- }
491
+ if (epoll_events[i].events & (EPOLLERR | EPOLLHUP))
492
+ ed->HandleError();
489
493
  }
490
494
  }
491
495
  else if (s < 0) {
@@ -520,7 +524,7 @@ bool EventMachine_t::_RunEpollOnce()
520
524
  assert (epfd != -1);
521
525
  int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
522
526
  // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
523
- if (e && (errno != ENOENT) && (errno != EBADF)) {
527
+ if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
524
528
  char buf [200];
525
529
  snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
526
530
  throw std::runtime_error (buf);
@@ -606,6 +610,9 @@ bool EventMachine_t::_RunKqueueOnce()
606
610
  EventableDescriptor *ed = (EventableDescriptor*) (ke->udata);
607
611
  assert (ed);
608
612
 
613
+ if (ed->IsWatchOnly() && ed->GetSocket() == INVALID_SOCKET)
614
+ break;
615
+
609
616
  if (ke->filter == EVFILT_READ)
610
617
  ed->Read();
611
618
  else if (ke->filter == EVFILT_WRITE)
@@ -647,7 +654,7 @@ bool EventMachine_t::_RunKqueueOnce()
647
654
  if (gCurrentLoopTime >= NextHeartbeatTime) {
648
655
  NextHeartbeatTime = gCurrentLoopTime + HeartbeatInterval;
649
656
 
650
- for (int i=0; i < Descriptors.size(); i++) {
657
+ for (unsigned int i=0; i < Descriptors.size(); i++) {
651
658
  EventableDescriptor *ed = Descriptors[i];
652
659
  assert (ed);
653
660
  ed->Heartbeat();
@@ -680,6 +687,7 @@ void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed)
680
687
  if (bEpoll) {
681
688
  assert (epfd != -1);
682
689
  assert (ed);
690
+ assert (ed->GetSocket() != INVALID_SOCKET);
683
691
  int e = epoll_ctl (epfd, EPOLL_CTL_MOD, ed->GetSocket(), ed->GetEpollEvent());
684
692
  if (e) {
685
693
  char buf [200];
@@ -701,6 +709,7 @@ SelectData_t::SelectData_t()
701
709
  maxsocket = 0;
702
710
  FD_ZERO (&fdreads);
703
711
  FD_ZERO (&fdwrites);
712
+ FD_ZERO (&fderrors);
704
713
  }
705
714
 
706
715
 
@@ -713,7 +722,7 @@ _SelectDataSelect
713
722
  static VALUE _SelectDataSelect (void *v)
714
723
  {
715
724
  SelectData_t *sd = (SelectData_t*)v;
716
- sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), NULL, &(sd->tv));
725
+ sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
717
726
  return Qnil;
718
727
  }
719
728
  #endif
@@ -730,7 +739,7 @@ int SelectData_t::_Select()
730
739
  #endif
731
740
 
732
741
  #ifndef HAVE_TBR
733
- return EmSelect (maxsocket+1, &fdreads, &fdwrites, NULL, &tv);
742
+ return EmSelect (maxsocket+1, &fdreads, &fdwrites, &fderrors, &tv);
734
743
  #endif
735
744
  }
736
745
  #endif
@@ -796,6 +805,8 @@ bool EventMachine_t::_RunSelectOnce()
796
805
  EventableDescriptor *ed = Descriptors[i];
797
806
  assert (ed);
798
807
  int sd = ed->GetSocket();
808
+ if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
809
+ continue;
799
810
  assert (sd != INVALID_SOCKET);
800
811
 
801
812
  if (ed->SelectForRead())
@@ -803,6 +814,13 @@ bool EventMachine_t::_RunSelectOnce()
803
814
  if (ed->SelectForWrite())
804
815
  FD_SET (sd, &(SelectData.fdwrites));
805
816
 
817
+ #ifdef OS_WIN32
818
+ /* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
819
+ Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
820
+ */
821
+ FD_SET (sd, &(SelectData.fderrors));
822
+ #endif
823
+
806
824
  if (SelectData.maxsocket < sd)
807
825
  SelectData.maxsocket = sd;
808
826
  }
@@ -831,12 +849,16 @@ bool EventMachine_t::_RunSelectOnce()
831
849
  EventableDescriptor *ed = Descriptors[i];
832
850
  assert (ed);
833
851
  int sd = ed->GetSocket();
852
+ if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
853
+ continue;
834
854
  assert (sd != INVALID_SOCKET);
835
855
 
836
856
  if (FD_ISSET (sd, &(SelectData.fdwrites)))
837
857
  ed->Write();
838
858
  if (FD_ISSET (sd, &(SelectData.fdreads)))
839
859
  ed->Read();
860
+ if (FD_ISSET (sd, &(SelectData.fderrors)))
861
+ ed->HandleError();
840
862
  }
841
863
 
842
864
  if (FD_ISSET (LoopBreakerReader, &(SelectData.fdreads)))
@@ -899,7 +921,7 @@ void EventMachine_t::_ReadLoopBreaker()
899
921
  char buffer [1024];
900
922
  read (LoopBreakerReader, buffer, sizeof(buffer));
901
923
  if (EventCallback)
902
- (*EventCallback)("", EM_LOOPBREAK_SIGNAL, "", 0);
924
+ (*EventCallback)(NULL, EM_LOOPBREAK_SIGNAL, "", 0);
903
925
  }
904
926
 
905
927
 
@@ -923,7 +945,7 @@ bool EventMachine_t::_RunTimers()
923
945
  if (i->first > gCurrentLoopTime)
924
946
  break;
925
947
  if (EventCallback)
926
- (*EventCallback) ("", EM_TIMER_FIRED, i->second.GetBinding().c_str(), i->second.GetBinding().length());
948
+ (*EventCallback) (NULL, EM_TIMER_FIRED, NULL, i->second.GetBinding());
927
949
  Timers.erase (i);
928
950
  }
929
951
  return true;
@@ -935,7 +957,7 @@ bool EventMachine_t::_RunTimers()
935
957
  EventMachine_t::InstallOneshotTimer
936
958
  ***********************************/
937
959
 
938
- const char *EventMachine_t::InstallOneshotTimer (int milliseconds)
960
+ const unsigned long EventMachine_t::InstallOneshotTimer (int milliseconds)
939
961
  {
940
962
  if (Timers.size() > MaxOutstandingTimers)
941
963
  return false;
@@ -960,12 +982,12 @@ const char *EventMachine_t::InstallOneshotTimer (int milliseconds)
960
982
  #endif
961
983
 
962
984
  Timer_t t;
963
- #ifdef OS_SOLARIS8
985
+ #ifndef HAVE_MAKE_PAIR
964
986
  multimap<Int64,Timer_t>::iterator i = Timers.insert (multimap<Int64,Timer_t>::value_type (fire_at, t));
965
987
  #else
966
988
  multimap<Int64,Timer_t>::iterator i = Timers.insert (make_pair (fire_at, t));
967
989
  #endif
968
- return i->second.GetBindingChars();
990
+ return i->second.GetBinding();
969
991
  }
970
992
 
971
993
 
@@ -973,7 +995,7 @@ const char *EventMachine_t::InstallOneshotTimer (int milliseconds)
973
995
  EventMachine_t::ConnectToServer
974
996
  *******************************/
975
997
 
976
- const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_port, const char *server, int port)
998
+ const unsigned long EventMachine_t::ConnectToServer (const char *bind_addr, int bind_port, const char *server, int port)
977
999
  {
978
1000
  /* We want to spend no more than a few seconds waiting for a connection
979
1001
  * to a remote host. So we use a nonblocking connect.
@@ -999,17 +1021,17 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
999
1021
  */
1000
1022
 
1001
1023
  if (!server || !*server || !port)
1002
- return NULL;
1024
+ throw std::runtime_error ("invalid server or port");
1003
1025
 
1004
1026
  int family, bind_size;
1005
1027
  struct sockaddr bind_as, *bind_as_ptr = name2address (server, port, &family, &bind_size);
1006
1028
  if (!bind_as_ptr)
1007
- return NULL;
1029
+ throw std::runtime_error ("unable to resolve server address");
1008
1030
  bind_as = *bind_as_ptr; // copy because name2address points to a static
1009
1031
 
1010
1032
  int sd = socket (family, SOCK_STREAM, 0);
1011
1033
  if (sd == INVALID_SOCKET)
1012
- return NULL;
1034
+ throw std::runtime_error ("unable to create new socket");
1013
1035
 
1014
1036
  /*
1015
1037
  sockaddr_in pin;
@@ -1043,7 +1065,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1043
1065
  // Set the new socket nonblocking.
1044
1066
  if (!SetSocketNonblocking (sd)) {
1045
1067
  closesocket (sd);
1046
- return NULL;
1068
+ throw std::runtime_error ("unable to set socket as non-blocking");
1047
1069
  }
1048
1070
  // Disable slow-start (Nagle algorithm).
1049
1071
  int one = 1;
@@ -1056,7 +1078,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1056
1078
  struct sockaddr *bind_to = name2address (bind_addr, bind_port, &bind_to_family, &bind_to_size);
1057
1079
  if (!bind_to) {
1058
1080
  closesocket (sd);
1059
- throw std::runtime_error ("bad bind address");
1081
+ throw std::runtime_error ("invalid bind address");
1060
1082
  }
1061
1083
  if (bind (sd, bind_to, bind_to_size) < 0) {
1062
1084
  closesocket (sd);
@@ -1064,7 +1086,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1064
1086
  }
1065
1087
  }
1066
1088
 
1067
- const char *out = NULL;
1089
+ unsigned long out = NULL;
1068
1090
 
1069
1091
  #ifdef OS_UNIX
1070
1092
  //if (connect (sd, (sockaddr*)&pin, sizeof pin) == 0) {
@@ -1093,7 +1115,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1093
1115
  throw std::runtime_error ("no connection allocated");
1094
1116
  cd->SetConnectPending (true);
1095
1117
  Add (cd);
1096
- out = cd->GetBinding().c_str();
1118
+ out = cd->GetBinding();
1097
1119
  }
1098
1120
  else if (errno == EINPROGRESS) {
1099
1121
  // Errno will generally always be EINPROGRESS, but on Linux
@@ -1111,7 +1133,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1111
1133
  throw std::runtime_error ("no connection allocated");
1112
1134
  cd->SetConnectPending (true);
1113
1135
  Add (cd);
1114
- out = cd->GetBinding().c_str();
1136
+ out = cd->GetBinding();
1115
1137
  }
1116
1138
  else {
1117
1139
  /* This could be connection refused or some such thing.
@@ -1131,7 +1153,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1131
1153
  throw std::runtime_error ("no connection allocated");
1132
1154
  cd->ScheduleClose (false);
1133
1155
  Add (cd);
1134
- out = cd->GetBinding().c_str();
1156
+ out = cd->GetBinding();
1135
1157
  }
1136
1158
  }
1137
1159
  else {
@@ -1159,7 +1181,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1159
1181
  throw std::runtime_error ("no connection allocated");
1160
1182
  cd->SetConnectPending (true);
1161
1183
  Add (cd);
1162
- out = cd->GetBinding().c_str();
1184
+ out = cd->GetBinding();
1163
1185
  }
1164
1186
  else {
1165
1187
  // The error from connect was something other then WSAEWOULDBLOCK.
@@ -1167,7 +1189,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1167
1189
 
1168
1190
  #endif
1169
1191
 
1170
- if (out == NULL)
1192
+ if (!out)
1171
1193
  closesocket (sd);
1172
1194
  return out;
1173
1195
  }
@@ -1176,7 +1198,7 @@ const char *EventMachine_t::ConnectToServer (const char *bind_addr, int bind_por
1176
1198
  EventMachine_t::ConnectToUnixServer
1177
1199
  ***********************************/
1178
1200
 
1179
- const char *EventMachine_t::ConnectToUnixServer (const char *server)
1201
+ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
1180
1202
  {
1181
1203
  /* Connect to a Unix-domain server, which by definition is running
1182
1204
  * on the same host.
@@ -1193,7 +1215,7 @@ const char *EventMachine_t::ConnectToUnixServer (const char *server)
1193
1215
  // The whole rest of this function is only compiled on Unix systems.
1194
1216
  #ifdef OS_UNIX
1195
1217
 
1196
- const char *out = NULL;
1218
+ unsigned long out = NULL;
1197
1219
 
1198
1220
  if (!server || !*server)
1199
1221
  return NULL;
@@ -1236,9 +1258,9 @@ const char *EventMachine_t::ConnectToUnixServer (const char *server)
1236
1258
  throw std::runtime_error ("no connection allocated");
1237
1259
  cd->SetConnectPending (true);
1238
1260
  Add (cd);
1239
- out = cd->GetBinding().c_str();
1261
+ out = cd->GetBinding();
1240
1262
 
1241
- if (out == NULL)
1263
+ if (!out)
1242
1264
  closesocket (fd);
1243
1265
 
1244
1266
  return out;
@@ -1249,7 +1271,7 @@ const char *EventMachine_t::ConnectToUnixServer (const char *server)
1249
1271
  EventMachine_t::AttachFD
1250
1272
  ************************/
1251
1273
 
1252
- const char *EventMachine_t::AttachFD (int fd, bool notify_readable, bool notify_writable)
1274
+ const unsigned long EventMachine_t::AttachFD (int fd, bool watch_mode)
1253
1275
  {
1254
1276
  #ifdef OS_UNIX
1255
1277
  if (fcntl(fd, F_GETFL, 0) < 0)
@@ -1279,22 +1301,19 @@ const char *EventMachine_t::AttachFD (int fd, bool notify_readable, bool notify_
1279
1301
  }
1280
1302
  }
1281
1303
 
1282
- SetSocketNonblocking(fd);
1304
+ if (!watch_mode)
1305
+ SetSocketNonblocking(fd);
1283
1306
 
1284
1307
  ConnectionDescriptor *cd = new ConnectionDescriptor (fd, this);
1285
1308
  if (!cd)
1286
1309
  throw std::runtime_error ("no connection allocated");
1287
1310
 
1311
+ cd->SetWatchOnly(watch_mode);
1288
1312
  cd->SetConnectPending (false);
1289
- cd->SetNotifyReadable (notify_readable);
1290
- cd->SetNotifyWritable (notify_writable);
1291
1313
 
1292
1314
  Add (cd);
1293
1315
 
1294
- const char *out = NULL;
1295
- out = cd->GetBinding().c_str();
1296
- if (out == NULL)
1297
- closesocket (fd);
1316
+ const unsigned long out = cd->GetBinding();
1298
1317
  return out;
1299
1318
  }
1300
1319
 
@@ -1307,10 +1326,11 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1307
1326
  if (!ed)
1308
1327
  throw std::runtime_error ("detaching bad descriptor");
1309
1328
 
1329
+ int fd = ed->GetSocket();
1330
+
1310
1331
  #ifdef HAVE_EPOLL
1311
1332
  if (bEpoll) {
1312
1333
  if (ed->GetSocket() != INVALID_SOCKET) {
1313
- assert (bEpoll); // wouldn't be in this method otherwise.
1314
1334
  assert (epfd != -1);
1315
1335
  int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
1316
1336
  // ENOENT or EBADF are not errors because the socket may be already closed when we get here.
@@ -1325,33 +1345,24 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1325
1345
 
1326
1346
  #ifdef HAVE_KQUEUE
1327
1347
  if (bKqueue) {
1348
+ // remove any read/write events for this fd
1328
1349
  struct kevent k;
1329
- EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_DELETE, 0, 0, ed);
1350
+ EV_SET (&k, ed->GetSocket(), EVFILT_READ | EVFILT_WRITE, EV_DELETE, 0, 0, ed);
1330
1351
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1331
- assert (t == 0);
1332
- }
1333
- #endif
1334
-
1335
- { // remove descriptor from lists
1336
- int i, j;
1337
- int nSockets = Descriptors.size();
1338
- for (i=0, j=0; i < nSockets; i++) {
1339
- EventableDescriptor *ted = Descriptors[i];
1340
- assert (ted);
1341
- if (ted != ed)
1342
- Descriptors [j++] = ted;
1352
+ if (t < 0 && (errno != ENOENT) && (errno != EBADF)) {
1353
+ char buf [200];
1354
+ snprintf (buf, sizeof(buf)-1, "unable to delete kqueue event: %s", strerror(errno));
1355
+ throw std::runtime_error (buf);
1343
1356
  }
1344
- while ((size_t)j < Descriptors.size())
1345
- Descriptors.pop_back();
1346
-
1347
- ModifiedDescriptors.erase (ed);
1348
1357
  }
1358
+ #endif
1349
1359
 
1350
- int fd = ed->GetSocket();
1360
+ // Prevent the descriptor from being modified, in case DetachFD was called from a timer or next_tick
1361
+ ModifiedDescriptors.erase (ed);
1351
1362
 
1352
- // We depend on ~EventableDescriptor not calling close() if the socket is invalid
1363
+ // Set MySocket = INVALID_SOCKET so ShouldDelete() is true (and the descriptor gets deleted and removed),
1364
+ // and also to prevent anyone from calling close() on the detached fd
1353
1365
  ed->SetSocketInvalid();
1354
- delete ed;
1355
1366
 
1356
1367
  return fd;
1357
1368
  }
@@ -1427,7 +1438,7 @@ struct sockaddr *name2address (const char *server, int port, int *family, int *b
1427
1438
  EventMachine_t::CreateTcpServer
1428
1439
  *******************************/
1429
1440
 
1430
- const char *EventMachine_t::CreateTcpServer (const char *server, int port)
1441
+ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int port)
1431
1442
  {
1432
1443
  /* Create a TCP-acceptor (server) socket and add it to the event machine.
1433
1444
  * Return the binding of the new acceptor to the caller.
@@ -1441,7 +1452,7 @@ const char *EventMachine_t::CreateTcpServer (const char *server, int port)
1441
1452
  if (!bind_here)
1442
1453
  return NULL;
1443
1454
 
1444
- const char *output_binding = NULL;
1455
+ unsigned long output_binding = NULL;
1445
1456
 
1446
1457
  //struct sockaddr_in sin;
1447
1458
 
@@ -1513,7 +1524,7 @@ const char *EventMachine_t::CreateTcpServer (const char *server, int port)
1513
1524
  if (!ad)
1514
1525
  throw std::runtime_error ("unable to allocate acceptor");
1515
1526
  Add (ad);
1516
- output_binding = ad->GetBinding().c_str();
1527
+ output_binding = ad->GetBinding();
1517
1528
  }
1518
1529
 
1519
1530
  return output_binding;
@@ -1529,9 +1540,9 @@ const char *EventMachine_t::CreateTcpServer (const char *server, int port)
1529
1540
  EventMachine_t::OpenDatagramSocket
1530
1541
  **********************************/
1531
1542
 
1532
- const char *EventMachine_t::OpenDatagramSocket (const char *address, int port)
1543
+ const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int port)
1533
1544
  {
1534
- const char *output_binding = NULL;
1545
+ unsigned long output_binding = NULL;
1535
1546
 
1536
1547
  int sd = socket (AF_INET, SOCK_DGRAM, 0);
1537
1548
  if (sd == INVALID_SOCKET)
@@ -1574,7 +1585,7 @@ const char *EventMachine_t::OpenDatagramSocket (const char *address, int port)
1574
1585
  if (!ds)
1575
1586
  throw std::runtime_error ("unable to allocate datagram-socket");
1576
1587
  Add (ds);
1577
- output_binding = ds->GetBinding().c_str();
1588
+ output_binding = ds->GetBinding();
1578
1589
  }
1579
1590
 
1580
1591
  return output_binding;
@@ -1613,7 +1624,11 @@ void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed)
1613
1624
  struct kevent k;
1614
1625
  EV_SET (&k, ed->GetSocket(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, ed);
1615
1626
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1616
- assert (t == 0);
1627
+ if (t < 0) {
1628
+ char buf [200];
1629
+ snprintf (buf, sizeof(buf)-1, "arm kqueue writer failed on %d: %s", ed->GetSocket(), strerror(errno));
1630
+ throw std::runtime_error (buf);
1631
+ }
1617
1632
  }
1618
1633
  #endif
1619
1634
  }
@@ -1631,7 +1646,11 @@ void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed)
1631
1646
  struct kevent k;
1632
1647
  EV_SET (&k, ed->GetSocket(), EVFILT_READ, EV_ADD, 0, 0, ed);
1633
1648
  int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
1634
- assert (t == 0);
1649
+ if (t < 0) {
1650
+ char buf [200];
1651
+ snprintf (buf, sizeof(buf)-1, "arm kqueue reader failed on %d: %s", ed->GetSocket(), strerror(errno));
1652
+ throw std::runtime_error (buf);
1653
+ }
1635
1654
  }
1636
1655
  #endif
1637
1656
  }
@@ -1743,7 +1762,7 @@ void EventMachine_t::Modify (EventableDescriptor *ed)
1743
1762
  EventMachine_t::_OpenFileForWriting
1744
1763
  ***********************************/
1745
1764
 
1746
- const char *EventMachine_t::_OpenFileForWriting (const char *filename)
1765
+ const unsigned long EventMachine_t::_OpenFileForWriting (const char *filename)
1747
1766
  {
1748
1767
  /*
1749
1768
  * Return the binding-text of the newly-opened file,
@@ -1759,7 +1778,7 @@ const char *EventMachine_t::_OpenFileForWriting (const char *filename)
1759
1778
  if (!fsd)
1760
1779
  throw std::runtime_error ("no file-stream allocated");
1761
1780
  Add (fsd);
1762
- return fsd->GetBinding().c_str();
1781
+ return fsd->GetBinding();
1763
1782
 
1764
1783
  }
1765
1784
 
@@ -1768,7 +1787,7 @@ const char *EventMachine_t::_OpenFileForWriting (const char *filename)
1768
1787
  EventMachine_t::CreateUnixDomainServer
1769
1788
  **************************************/
1770
1789
 
1771
- const char *EventMachine_t::CreateUnixDomainServer (const char *filename)
1790
+ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename)
1772
1791
  {
1773
1792
  /* Create a UNIX-domain acceptor (server) socket and add it to the event machine.
1774
1793
  * Return the binding of the new acceptor to the caller.
@@ -1783,7 +1802,7 @@ const char *EventMachine_t::CreateUnixDomainServer (const char *filename)
1783
1802
 
1784
1803
  // The whole rest of this function is only compiled on Unix systems.
1785
1804
  #ifdef OS_UNIX
1786
- const char *output_binding = NULL;
1805
+ unsigned long output_binding = NULL;
1787
1806
 
1788
1807
  struct sockaddr_un s_sun;
1789
1808
 
@@ -1836,7 +1855,7 @@ const char *EventMachine_t::CreateUnixDomainServer (const char *filename)
1836
1855
  if (!ad)
1837
1856
  throw std::runtime_error ("unable to allocate acceptor");
1838
1857
  Add (ad);
1839
- output_binding = ad->GetBinding().c_str();
1858
+ output_binding = ad->GetBinding();
1840
1859
  }
1841
1860
 
1842
1861
  return output_binding;
@@ -1882,7 +1901,7 @@ const char *EventMachine_t::Popen (const char *cmd, const char *mode)
1882
1901
  if (!pd)
1883
1902
  throw std::runtime_error ("unable to allocate pipe");
1884
1903
  Add (pd);
1885
- output_binding = pd->GetBinding().c_str();
1904
+ output_binding = pd->GetBinding();
1886
1905
  }
1887
1906
 
1888
1907
  return output_binding;
@@ -1894,7 +1913,7 @@ const char *EventMachine_t::Popen (const char *cmd, const char *mode)
1894
1913
  EventMachine_t::Socketpair
1895
1914
  **************************/
1896
1915
 
1897
- const char *EventMachine_t::Socketpair (char * const*cmd_strings)
1916
+ const unsigned long EventMachine_t::Socketpair (char * const*cmd_strings)
1898
1917
  {
1899
1918
  #ifdef OS_WIN32
1900
1919
  throw std::runtime_error ("socketpair is currently unavailable on this platform");
@@ -1912,7 +1931,7 @@ const char *EventMachine_t::Socketpair (char * const*cmd_strings)
1912
1931
  if ((j==0) || (j==100))
1913
1932
  return NULL;
1914
1933
 
1915
- const char *output_binding = NULL;
1934
+ unsigned long output_binding = NULL;
1916
1935
 
1917
1936
  int sv[2];
1918
1937
  if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sv) < 0)
@@ -1936,7 +1955,7 @@ const char *EventMachine_t::Socketpair (char * const*cmd_strings)
1936
1955
  if (!pd)
1937
1956
  throw std::runtime_error ("unable to allocate pipe");
1938
1957
  Add (pd);
1939
- output_binding = pd->GetBinding().c_str();
1958
+ output_binding = pd->GetBinding();
1940
1959
  }
1941
1960
  else if (f == 0) {
1942
1961
  close (sv[0]);
@@ -1958,13 +1977,13 @@ const char *EventMachine_t::Socketpair (char * const*cmd_strings)
1958
1977
  EventMachine_t::OpenKeyboard
1959
1978
  ****************************/
1960
1979
 
1961
- const char *EventMachine_t::OpenKeyboard()
1980
+ const unsigned long EventMachine_t::OpenKeyboard()
1962
1981
  {
1963
1982
  KeyboardDescriptor *kd = new KeyboardDescriptor (this);
1964
1983
  if (!kd)
1965
1984
  throw std::runtime_error ("no keyboard-object allocated");
1966
1985
  Add (kd);
1967
- return kd->GetBinding().c_str();
1986
+ return kd->GetBinding();
1968
1987
  }
1969
1988
 
1970
1989
 
@@ -1982,7 +2001,7 @@ int EventMachine_t::GetConnectionCount ()
1982
2001
  EventMachine_t::WatchPid
1983
2002
  ************************/
1984
2003
 
1985
- const char *EventMachine_t::WatchPid (int pid)
2004
+ const unsigned long EventMachine_t::WatchPid (int pid)
1986
2005
  {
1987
2006
  #ifdef HAVE_KQUEUE
1988
2007
  if (!bKqueue)
@@ -2006,7 +2025,7 @@ const char *EventMachine_t::WatchPid (int pid)
2006
2025
  Bindable_t* b = new Bindable_t();
2007
2026
  Pids.insert(make_pair (pid, b));
2008
2027
 
2009
- return b->GetBinding().c_str();
2028
+ return b->GetBinding();
2010
2029
  #endif
2011
2030
 
2012
2031
  throw std::runtime_error("no pid watching support on this system");
@@ -2026,21 +2045,21 @@ void EventMachine_t::UnwatchPid (int pid)
2026
2045
  struct kevent k;
2027
2046
 
2028
2047
  EV_SET(&k, pid, EVFILT_PROC, EV_DELETE, 0, 0, 0);
2029
- int t = kevent (kqfd, &k, 1, NULL, 0, NULL);
2048
+ /*int t =*/ kevent (kqfd, &k, 1, NULL, 0, NULL);
2030
2049
  // t==-1 if the process already exited; ignore this for now
2031
2050
  #endif
2032
2051
 
2033
2052
  if (EventCallback)
2034
- (*EventCallback)(b->GetBinding().c_str(), EM_CONNECTION_UNBOUND, NULL, 0);
2053
+ (*EventCallback)(b->GetBinding(), EM_CONNECTION_UNBOUND, NULL, 0);
2035
2054
 
2036
2055
  delete b;
2037
2056
  }
2038
2057
 
2039
- void EventMachine_t::UnwatchPid (const char *sig)
2058
+ void EventMachine_t::UnwatchPid (const unsigned long sig)
2040
2059
  {
2041
2060
  for(map<int, Bindable_t*>::iterator i=Pids.begin(); i != Pids.end(); i++)
2042
2061
  {
2043
- if (strncmp(i->second->GetBinding().c_str(), sig, strlen(sig)) == 0) {
2062
+ if (i->second->GetBinding() == sig) {
2044
2063
  UnwatchPid (i->first);
2045
2064
  return;
2046
2065
  }
@@ -2054,7 +2073,7 @@ void EventMachine_t::UnwatchPid (const char *sig)
2054
2073
  EventMachine_t::WatchFile
2055
2074
  *************************/
2056
2075
 
2057
- const char *EventMachine_t::WatchFile (const char *fpath)
2076
+ const unsigned long EventMachine_t::WatchFile (const char *fpath)
2058
2077
  {
2059
2078
  struct stat sb;
2060
2079
  int sres;
@@ -2101,7 +2120,7 @@ const char *EventMachine_t::WatchFile (const char *fpath)
2101
2120
  Bindable_t* b = new Bindable_t();
2102
2121
  Files.insert(make_pair (wd, b));
2103
2122
 
2104
- return b->GetBinding().c_str();
2123
+ return b->GetBinding();
2105
2124
  }
2106
2125
 
2107
2126
  throw std::runtime_error("no file watching support on this system"); // is this the right thing to do?
@@ -2126,16 +2145,16 @@ void EventMachine_t::UnwatchFile (int wd)
2126
2145
  #endif
2127
2146
 
2128
2147
  if (EventCallback)
2129
- (*EventCallback)(b->GetBinding().c_str(), EM_CONNECTION_UNBOUND, NULL, 0);
2148
+ (*EventCallback)(b->GetBinding(), EM_CONNECTION_UNBOUND, NULL, 0);
2130
2149
 
2131
2150
  delete b;
2132
2151
  }
2133
2152
 
2134
- void EventMachine_t::UnwatchFile (const char *sig)
2153
+ void EventMachine_t::UnwatchFile (const unsigned long sig)
2135
2154
  {
2136
2155
  for(map<int, Bindable_t*>::iterator i=Files.begin(); i != Files.end(); i++)
2137
2156
  {
2138
- if (strncmp(i->second->GetBinding().c_str(), sig, strlen(sig)) == 0) {
2157
+ if (i->second->GetBinding() == sig) {
2139
2158
  UnwatchFile (i->first);
2140
2159
  return;
2141
2160
  }
@@ -2158,12 +2177,12 @@ void EventMachine_t::_ReadInotifyEvents()
2158
2177
  while (read(inotify->GetSocket(), &event, INOTIFY_EVENT_SIZE) > 0) {
2159
2178
  assert(event.len == 0);
2160
2179
  if (event.mask & IN_MODIFY)
2161
- (*EventCallback)(Files [event.wd]->GetBinding().c_str(), EM_CONNECTION_READ, "modified", 8);
2180
+ (*EventCallback)(Files [event.wd]->GetBinding(), EM_CONNECTION_READ, "modified", 8);
2162
2181
  if (event.mask & IN_MOVE_SELF)
2163
- (*EventCallback)(Files [event.wd]->GetBinding().c_str(), EM_CONNECTION_READ, "moved", 5);
2182
+ (*EventCallback)(Files [event.wd]->GetBinding(), EM_CONNECTION_READ, "moved", 5);
2164
2183
  if (event.mask & IN_DELETE_SELF) {
2165
- (*EventCallback)(Files [event.wd]->GetBinding().c_str(), EM_CONNECTION_READ, "deleted", 7);
2166
- UnwatchFile (event.wd);
2184
+ (*EventCallback)(Files [event.wd]->GetBinding(), EM_CONNECTION_READ, "deleted", 7);
2185
+ UnwatchFile ((int)event.wd);
2167
2186
  }
2168
2187
  }
2169
2188
  #endif
@@ -2180,11 +2199,11 @@ void EventMachine_t::_HandleKqueuePidEvent(struct kevent *event)
2180
2199
  assert(EventCallback);
2181
2200
 
2182
2201
  if (event->fflags & NOTE_FORK)
2183
- (*EventCallback)(Pids [(int) event->ident]->GetBinding().c_str(), EM_CONNECTION_READ, "fork", 4);
2202
+ (*EventCallback)(Pids [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "fork", 4);
2184
2203
  if (event->fflags & NOTE_EXIT) {
2185
- (*EventCallback)(Pids [(int) event->ident]->GetBinding().c_str(), EM_CONNECTION_READ, "exit", 4);
2204
+ (*EventCallback)(Pids [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "exit", 4);
2186
2205
  // stop watching the pid if it died
2187
- UnwatchPid (event->ident);
2206
+ UnwatchPid ((int)event->ident);
2188
2207
  }
2189
2208
  }
2190
2209
  #endif
@@ -2200,12 +2219,12 @@ void EventMachine_t::_HandleKqueueFileEvent(struct kevent *event)
2200
2219
  assert(EventCallback);
2201
2220
 
2202
2221
  if (event->fflags & NOTE_WRITE)
2203
- (*EventCallback)(Files [(int) event->ident]->GetBinding().c_str(), EM_CONNECTION_READ, "modified", 8);
2222
+ (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "modified", 8);
2204
2223
  if (event->fflags & NOTE_RENAME)
2205
- (*EventCallback)(Files [(int) event->ident]->GetBinding().c_str(), EM_CONNECTION_READ, "moved", 5);
2224
+ (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "moved", 5);
2206
2225
  if (event->fflags & NOTE_DELETE) {
2207
- (*EventCallback)(Files [(int) event->ident]->GetBinding().c_str(), EM_CONNECTION_READ, "deleted", 7);
2208
- UnwatchFile (event->ident);
2226
+ (*EventCallback)(Files [(int) event->ident]->GetBinding(), EM_CONNECTION_READ, "deleted", 7);
2227
+ UnwatchFile ((int)event->ident);
2209
2228
  }
2210
2229
  }
2211
2230
  #endif