eventmachine 1.0.7-java → 1.0.8-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +1 -1
- data/ext/binder.cpp +9 -9
- data/ext/binder.h +5 -5
- data/ext/cmain.cpp +68 -55
- data/ext/ed.cpp +106 -70
- data/ext/ed.h +19 -13
- data/ext/em.cpp +228 -194
- data/ext/em.h +33 -28
- data/ext/eventmachine.h +53 -52
- data/ext/extconf.rb +26 -3
- data/ext/fastfilereader/rubymain.cpp +1 -1
- data/ext/kb.cpp +1 -1
- data/ext/pipe.cpp +4 -2
- data/ext/project.h +6 -0
- data/ext/rubymain.cpp +218 -188
- data/ext/ssl.cpp +7 -7
- data/ext/ssl.h +1 -1
- data/lib/em/protocols/line_and_text.rb +1 -0
- data/lib/em/protocols/linetext2.rb +44 -38
- data/lib/em/protocols/smtpclient.rb +60 -31
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +9 -1
- data/tests/test_ltp2.rb +20 -0
- data/tests/test_smtpclient.rb +20 -0
- metadata +4 -4
data/ext/em.cpp
CHANGED
@@ -38,6 +38,33 @@ static unsigned int SimultaneousAcceptCount = 10;
|
|
38
38
|
*/
|
39
39
|
static struct sockaddr *name2address (const char *server, int port, int *family, int *bind_size);
|
40
40
|
|
41
|
+
/* Internal helper to create a socket with SOCK_CLOEXEC set, and fall
|
42
|
+
* back to fcntl'ing it if the headers/runtime don't support it.
|
43
|
+
*/
|
44
|
+
|
45
|
+
int EmSocket (int domain, int type, int protocol)
|
46
|
+
{
|
47
|
+
int sd;
|
48
|
+
#ifdef HAVE_SOCKET_CLOEXEC
|
49
|
+
sd = socket (domain, type | SOCK_CLOEXEC, protocol);
|
50
|
+
if (sd < 0) {
|
51
|
+
sd = socket (domain, type, protocol);
|
52
|
+
if (sd < 0) {
|
53
|
+
return sd;
|
54
|
+
}
|
55
|
+
SetFdCloexec(sd);
|
56
|
+
}
|
57
|
+
#else
|
58
|
+
sd = socket (domain, type, protocol);
|
59
|
+
if (sd < 0) {
|
60
|
+
return sd;
|
61
|
+
}
|
62
|
+
SetFdCloexec(sd);
|
63
|
+
#endif
|
64
|
+
return sd;
|
65
|
+
}
|
66
|
+
|
67
|
+
|
41
68
|
/***************************************
|
42
69
|
STATIC EventMachine_t::GetMaxTimerCount
|
43
70
|
***************************************/
|
@@ -83,24 +110,29 @@ void EventMachine_t::SetSimultaneousAcceptCount (int count)
|
|
83
110
|
EventMachine_t::EventMachine_t
|
84
111
|
******************************/
|
85
112
|
|
86
|
-
EventMachine_t::EventMachine_t (EMCallback event_callback):
|
113
|
+
EventMachine_t::EventMachine_t (EMCallback event_callback, Poller_t poller):
|
87
114
|
NumCloseScheduled (0),
|
88
115
|
HeartbeatInterval(2000000),
|
89
116
|
EventCallback (event_callback),
|
90
|
-
NextHeartbeatTime (0),
|
91
117
|
LoopBreakerReader (-1),
|
92
118
|
LoopBreakerWriter (-1),
|
93
119
|
bTerminateSignalReceived (false),
|
94
|
-
|
120
|
+
Poller (poller),
|
95
121
|
epfd (-1),
|
96
|
-
|
97
|
-
|
98
|
-
inotify (NULL)
|
122
|
+
kqfd (-1)
|
123
|
+
#ifdef HAVE_INOTIFY
|
124
|
+
, inotify (NULL)
|
125
|
+
#endif
|
99
126
|
{
|
100
127
|
// Default time-slice is just smaller than one hundred mills.
|
101
128
|
Quantum.tv_sec = 0;
|
102
129
|
Quantum.tv_usec = 90000;
|
103
130
|
|
131
|
+
// Override the requested poller back to default if needed.
|
132
|
+
#if !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE)
|
133
|
+
Poller = Poller_Default;
|
134
|
+
#endif
|
135
|
+
|
104
136
|
/* Initialize monotonic timekeeping on OS X before the first call to GetRealTime */
|
105
137
|
#ifdef OS_DARWIN
|
106
138
|
(void) mach_timebase_info(&mach_timebase);
|
@@ -157,59 +189,25 @@ EventMachine_t::~EventMachine_t()
|
|
157
189
|
}
|
158
190
|
|
159
191
|
|
160
|
-
/*************************
|
161
|
-
EventMachine_t::_UseEpoll
|
162
|
-
*************************/
|
163
|
-
|
164
|
-
void EventMachine_t::_UseEpoll()
|
165
|
-
{
|
166
|
-
/* Temporary.
|
167
|
-
* Use an internal flag to switch in epoll-based functionality until we determine
|
168
|
-
* how it should be integrated properly and the extent of the required changes.
|
169
|
-
* A permanent solution needs to allow the integration of additional technologies,
|
170
|
-
* like kqueue and Solaris's events.
|
171
|
-
*/
|
172
|
-
|
173
|
-
#ifdef HAVE_EPOLL
|
174
|
-
bEpoll = true;
|
175
|
-
#endif
|
176
|
-
}
|
177
|
-
|
178
|
-
/**************************
|
179
|
-
EventMachine_t::_UseKqueue
|
180
|
-
**************************/
|
181
|
-
|
182
|
-
void EventMachine_t::_UseKqueue()
|
183
|
-
{
|
184
|
-
/* Temporary.
|
185
|
-
* See comments under _UseEpoll.
|
186
|
-
*/
|
187
|
-
|
188
|
-
#ifdef HAVE_KQUEUE
|
189
|
-
bKqueue = true;
|
190
|
-
#endif
|
191
|
-
}
|
192
|
-
|
193
|
-
|
194
192
|
/****************************
|
195
193
|
EventMachine_t::ScheduleHalt
|
196
194
|
****************************/
|
197
195
|
|
198
196
|
void EventMachine_t::ScheduleHalt()
|
199
197
|
{
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
198
|
+
/* This is how we stop the machine.
|
199
|
+
* This can be called by clients. Signal handlers will probably
|
200
|
+
* set the global flag.
|
201
|
+
* For now this means there can only be one EventMachine ever running at a time.
|
202
|
+
*
|
203
|
+
* IMPORTANT: keep this light, fast, and async-safe. Don't do anything frisky in here,
|
204
|
+
* because it may be called from signal handlers invoked from code that we don't
|
205
|
+
* control. At this writing (20Sep06), EM does NOT install any signal handlers of
|
206
|
+
* its own.
|
207
|
+
*
|
208
|
+
* We need a FAQ. And one of the questions is: how do I stop EM when Ctrl-C happens?
|
209
|
+
* The answer is to call evma_stop_machine, which calls here, from a SIGINT handler.
|
210
|
+
*/
|
213
211
|
bTerminateSignalReceived = true;
|
214
212
|
|
215
213
|
/* Signal the loopbreaker so we break out of long-running select/epoll/kqueue and
|
@@ -244,33 +242,33 @@ void EventMachine_t::SetTimerQuantum (int interval)
|
|
244
242
|
|
245
243
|
void EventMachine_t::SetuidString (const char *username)
|
246
244
|
{
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
245
|
+
/* This method takes a caller-supplied username and tries to setuid
|
246
|
+
* to that user. There is no meaningful implementation (and no error)
|
247
|
+
* on Windows. On Unix, a failure to setuid the caller-supplied string
|
248
|
+
* causes a fatal abort, because presumably the program is calling here
|
249
|
+
* in order to fulfill a security requirement. If we fail silently,
|
250
|
+
* the user may continue to run with too much privilege.
|
251
|
+
*
|
252
|
+
* TODO, we need to decide on and document a way of generating C++ level errors
|
253
|
+
* that can be wrapped in documented Ruby exceptions, so users can catch
|
254
|
+
* and handle them. And distinguish it from errors that we WON'T let the Ruby
|
255
|
+
* user catch (like security-violations and resource-overallocation).
|
256
|
+
* A setuid failure here would be in the latter category.
|
257
|
+
*/
|
260
258
|
|
261
|
-
|
262
|
-
|
263
|
-
|
259
|
+
#ifdef OS_UNIX
|
260
|
+
if (!username || !*username)
|
261
|
+
throw std::runtime_error ("setuid_string failed: no username specified");
|
264
262
|
|
265
|
-
|
266
|
-
|
267
|
-
|
263
|
+
struct passwd *p = getpwnam (username);
|
264
|
+
if (!p)
|
265
|
+
throw std::runtime_error ("setuid_string failed: unknown username");
|
268
266
|
|
269
|
-
|
270
|
-
|
267
|
+
if (setuid (p->pw_uid) != 0)
|
268
|
+
throw std::runtime_error ("setuid_string failed: no setuid");
|
271
269
|
|
272
|
-
|
273
|
-
|
270
|
+
// Success.
|
271
|
+
#endif
|
274
272
|
}
|
275
273
|
|
276
274
|
|
@@ -309,7 +307,7 @@ EventMachine_t::SignalLoopBreaker
|
|
309
307
|
void EventMachine_t::SignalLoopBreaker()
|
310
308
|
{
|
311
309
|
#ifdef OS_UNIX
|
312
|
-
write (LoopBreakerWriter, "", 1);
|
310
|
+
(void)write (LoopBreakerWriter, "", 1);
|
313
311
|
#endif
|
314
312
|
#ifdef OS_WIN32
|
315
313
|
sendto (LoopBreakerReader, "", 0, 0, (struct sockaddr*)&(LoopBreakerTarget), sizeof(LoopBreakerTarget));
|
@@ -333,8 +331,18 @@ void EventMachine_t::_InitializeLoopBreaker()
|
|
333
331
|
|
334
332
|
#ifdef OS_UNIX
|
335
333
|
int fd[2];
|
334
|
+
#if defined (HAVE_CLOEXEC) && defined (HAVE_PIPE2)
|
335
|
+
int pipestatus = pipe2(fd, O_CLOEXEC);
|
336
|
+
if (pipestatus < 0) {
|
337
|
+
if (pipe(fd))
|
338
|
+
throw std::runtime_error (strerror(errno));
|
339
|
+
}
|
340
|
+
#else
|
336
341
|
if (pipe (fd))
|
337
342
|
throw std::runtime_error (strerror(errno));
|
343
|
+
#endif
|
344
|
+
if (!SetFdCloexec(fd[0]) || !SetFdCloexec(fd[1]))
|
345
|
+
throw std::runtime_error (strerror(errno));
|
338
346
|
|
339
347
|
LoopBreakerWriter = fd[1];
|
340
348
|
LoopBreakerReader = fd[0];
|
@@ -345,7 +353,7 @@ void EventMachine_t::_InitializeLoopBreaker()
|
|
345
353
|
#endif
|
346
354
|
|
347
355
|
#ifdef OS_WIN32
|
348
|
-
int sd =
|
356
|
+
int sd = EmSocket (AF_INET, SOCK_DGRAM, 0);
|
349
357
|
if (sd == INVALID_SOCKET)
|
350
358
|
throw std::runtime_error ("no loop breaker socket");
|
351
359
|
SetSocketNonblocking (sd);
|
@@ -367,6 +375,43 @@ void EventMachine_t::_InitializeLoopBreaker()
|
|
367
375
|
throw std::runtime_error ("no loop breaker");
|
368
376
|
LoopBreakerReader = sd;
|
369
377
|
#endif
|
378
|
+
|
379
|
+
#ifdef HAVE_EPOLL
|
380
|
+
if (Poller == Poller_Epoll) {
|
381
|
+
epfd = epoll_create (MaxEpollDescriptors);
|
382
|
+
if (epfd == -1) {
|
383
|
+
char buf[200];
|
384
|
+
snprintf (buf, sizeof(buf)-1, "unable to create epoll descriptor: %s", strerror(errno));
|
385
|
+
throw std::runtime_error (buf);
|
386
|
+
}
|
387
|
+
int cloexec = fcntl (epfd, F_GETFD, 0);
|
388
|
+
assert (cloexec >= 0);
|
389
|
+
cloexec |= FD_CLOEXEC;
|
390
|
+
fcntl (epfd, F_SETFD, cloexec);
|
391
|
+
|
392
|
+
assert (LoopBreakerReader >= 0);
|
393
|
+
LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
|
394
|
+
assert (ld);
|
395
|
+
Add (ld);
|
396
|
+
}
|
397
|
+
#endif
|
398
|
+
|
399
|
+
#ifdef HAVE_KQUEUE
|
400
|
+
if (Poller == Poller_Kqueue) {
|
401
|
+
kqfd = kqueue();
|
402
|
+
if (kqfd == -1) {
|
403
|
+
char buf[200];
|
404
|
+
snprintf (buf, sizeof(buf)-1, "unable to create kqueue descriptor: %s", strerror(errno));
|
405
|
+
throw std::runtime_error (buf);
|
406
|
+
}
|
407
|
+
// cloexec not needed. By definition, kqueues are not carried across forks.
|
408
|
+
|
409
|
+
assert (LoopBreakerReader >= 0);
|
410
|
+
LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
|
411
|
+
assert (ld);
|
412
|
+
Add (ld);
|
413
|
+
}
|
414
|
+
#endif
|
370
415
|
}
|
371
416
|
|
372
417
|
/***************************
|
@@ -511,75 +556,44 @@ EventMachine_t::Run
|
|
511
556
|
|
512
557
|
void EventMachine_t::Run()
|
513
558
|
{
|
514
|
-
|
515
|
-
if (bEpoll) {
|
516
|
-
epfd = epoll_create (MaxEpollDescriptors);
|
517
|
-
if (epfd == -1) {
|
518
|
-
char buf[200];
|
519
|
-
snprintf (buf, sizeof(buf)-1, "unable to create epoll descriptor: %s", strerror(errno));
|
520
|
-
throw std::runtime_error (buf);
|
521
|
-
}
|
522
|
-
int cloexec = fcntl (epfd, F_GETFD, 0);
|
523
|
-
assert (cloexec >= 0);
|
524
|
-
cloexec |= FD_CLOEXEC;
|
525
|
-
fcntl (epfd, F_SETFD, cloexec);
|
526
|
-
|
527
|
-
assert (LoopBreakerReader >= 0);
|
528
|
-
LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
|
529
|
-
assert (ld);
|
530
|
-
Add (ld);
|
531
|
-
}
|
532
|
-
#endif
|
533
|
-
|
534
|
-
#ifdef HAVE_KQUEUE
|
535
|
-
if (bKqueue) {
|
536
|
-
kqfd = kqueue();
|
537
|
-
if (kqfd == -1) {
|
538
|
-
char buf[200];
|
539
|
-
snprintf (buf, sizeof(buf)-1, "unable to create kqueue descriptor: %s", strerror(errno));
|
540
|
-
throw std::runtime_error (buf);
|
541
|
-
}
|
542
|
-
// cloexec not needed. By definition, kqueues are not carried across forks.
|
543
|
-
|
544
|
-
assert (LoopBreakerReader >= 0);
|
545
|
-
LoopbreakDescriptor *ld = new LoopbreakDescriptor (LoopBreakerReader, this);
|
546
|
-
assert (ld);
|
547
|
-
Add (ld);
|
548
|
-
}
|
549
|
-
#endif
|
550
|
-
|
551
|
-
while (true) {
|
552
|
-
_UpdateTime();
|
553
|
-
_RunTimers();
|
554
|
-
|
555
|
-
/* _Add must precede _Modify because the same descriptor might
|
556
|
-
* be on both lists during the same pass through the machine,
|
557
|
-
* and to modify a descriptor before adding it would fail.
|
558
|
-
*/
|
559
|
-
_AddNewDescriptors();
|
560
|
-
_ModifyDescriptors();
|
561
|
-
|
562
|
-
_RunOnce();
|
563
|
-
if (bTerminateSignalReceived)
|
564
|
-
break;
|
565
|
-
}
|
559
|
+
while (RunOnce()) ;
|
566
560
|
}
|
567
561
|
|
562
|
+
/***********************
|
563
|
+
EventMachine_t::RunOnce
|
564
|
+
***********************/
|
568
565
|
|
569
|
-
|
570
|
-
EventMachine_t::_RunOnce
|
571
|
-
************************/
|
572
|
-
|
573
|
-
void EventMachine_t::_RunOnce()
|
566
|
+
bool EventMachine_t::RunOnce()
|
574
567
|
{
|
575
|
-
|
568
|
+
_UpdateTime();
|
569
|
+
_RunTimers();
|
570
|
+
|
571
|
+
/* _Add must precede _Modify because the same descriptor might
|
572
|
+
* be on both lists during the same pass through the machine,
|
573
|
+
* and to modify a descriptor before adding it would fail.
|
574
|
+
*/
|
575
|
+
_AddNewDescriptors();
|
576
|
+
_ModifyDescriptors();
|
577
|
+
|
578
|
+
switch (Poller) {
|
579
|
+
case Poller_Epoll:
|
576
580
|
_RunEpollOnce();
|
577
|
-
|
581
|
+
break;
|
582
|
+
case Poller_Kqueue:
|
578
583
|
_RunKqueueOnce();
|
579
|
-
|
584
|
+
break;
|
585
|
+
case Poller_Default:
|
580
586
|
_RunSelectOnce();
|
587
|
+
break;
|
588
|
+
}
|
589
|
+
|
581
590
|
_DispatchHeartbeats();
|
582
591
|
_CleanupSockets();
|
592
|
+
|
593
|
+
if (bTerminateSignalReceived)
|
594
|
+
return false;
|
595
|
+
|
596
|
+
return true;
|
583
597
|
}
|
584
598
|
|
585
599
|
|
@@ -660,9 +674,9 @@ void EventMachine_t::_RunEpollOnce()
|
|
660
674
|
EventMachine_t::_RunKqueueOnce
|
661
675
|
******************************/
|
662
676
|
|
677
|
+
#ifdef HAVE_KQUEUE
|
663
678
|
void EventMachine_t::_RunKqueueOnce()
|
664
679
|
{
|
665
|
-
#ifdef HAVE_KQUEUE
|
666
680
|
assert (kqfd != -1);
|
667
681
|
int k;
|
668
682
|
|
@@ -740,10 +754,13 @@ void EventMachine_t::_RunKqueueOnce()
|
|
740
754
|
rb_thread_schedule();
|
741
755
|
}
|
742
756
|
#endif
|
743
|
-
|
757
|
+
}
|
758
|
+
#else
|
759
|
+
void EventMachine_t::_RunKqueueOnce()
|
760
|
+
{
|
744
761
|
throw std::runtime_error ("kqueue is not implemented on this platform");
|
745
|
-
#endif
|
746
762
|
}
|
763
|
+
#endif
|
747
764
|
|
748
765
|
|
749
766
|
/*********************************
|
@@ -818,7 +835,7 @@ void EventMachine_t::_CleanupSockets()
|
|
818
835
|
assert (ed);
|
819
836
|
if (ed->ShouldDelete()) {
|
820
837
|
#ifdef HAVE_EPOLL
|
821
|
-
if (
|
838
|
+
if (Poller == Poller_Epoll) {
|
822
839
|
assert (epfd != -1);
|
823
840
|
if (ed->GetSocket() != INVALID_SOCKET) {
|
824
841
|
int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
|
@@ -845,10 +862,10 @@ void EventMachine_t::_CleanupSockets()
|
|
845
862
|
EventMachine_t::_ModifyEpollEvent
|
846
863
|
*********************************/
|
847
864
|
|
865
|
+
#ifdef HAVE_EPOLL
|
848
866
|
void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed)
|
849
867
|
{
|
850
|
-
|
851
|
-
if (bEpoll) {
|
868
|
+
if (Poller == Poller_Epoll) {
|
852
869
|
assert (epfd != -1);
|
853
870
|
assert (ed);
|
854
871
|
assert (ed->GetSocket() != INVALID_SOCKET);
|
@@ -859,9 +876,10 @@ void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed)
|
|
859
876
|
throw std::runtime_error (buf);
|
860
877
|
}
|
861
878
|
}
|
862
|
-
#endif
|
863
879
|
}
|
864
|
-
|
880
|
+
#else
|
881
|
+
void EventMachine_t::_ModifyEpollEvent (EventableDescriptor *ed UNUSED) { }
|
882
|
+
#endif
|
865
883
|
|
866
884
|
|
867
885
|
/**************************
|
@@ -1082,7 +1100,7 @@ void EventMachine_t::_ReadLoopBreaker()
|
|
1082
1100
|
* and send a loop-break event back to user code.
|
1083
1101
|
*/
|
1084
1102
|
char buffer [1024];
|
1085
|
-
read (LoopBreakerReader, buffer, sizeof(buffer));
|
1103
|
+
(void)read (LoopBreakerReader, buffer, sizeof(buffer));
|
1086
1104
|
if (EventCallback)
|
1087
1105
|
(*EventCallback)(0, EM_LOOPBREAK_SIGNAL, "", 0);
|
1088
1106
|
}
|
@@ -1118,7 +1136,7 @@ void EventMachine_t::_RunTimers()
|
|
1118
1136
|
EventMachine_t::InstallOneshotTimer
|
1119
1137
|
***********************************/
|
1120
1138
|
|
1121
|
-
const
|
1139
|
+
const uintptr_t EventMachine_t::InstallOneshotTimer (int milliseconds)
|
1122
1140
|
{
|
1123
1141
|
if (Timers.size() > MaxOutstandingTimers)
|
1124
1142
|
return false;
|
@@ -1140,7 +1158,7 @@ const unsigned long EventMachine_t::InstallOneshotTimer (int milliseconds)
|
|
1140
1158
|
EventMachine_t::ConnectToServer
|
1141
1159
|
*******************************/
|
1142
1160
|
|
1143
|
-
const
|
1161
|
+
const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind_port, const char *server, int port)
|
1144
1162
|
{
|
1145
1163
|
/* We want to spend no more than a few seconds waiting for a connection
|
1146
1164
|
* to a remote host. So we use a nonblocking connect.
|
@@ -1174,7 +1192,7 @@ const unsigned long EventMachine_t::ConnectToServer (const char *bind_addr, int
|
|
1174
1192
|
throw std::runtime_error ("unable to resolve server address");
|
1175
1193
|
bind_as = *bind_as_ptr; // copy because name2address points to a static
|
1176
1194
|
|
1177
|
-
int sd =
|
1195
|
+
int sd = EmSocket (family, SOCK_STREAM, 0);
|
1178
1196
|
if (sd == INVALID_SOCKET) {
|
1179
1197
|
char buf [200];
|
1180
1198
|
snprintf (buf, sizeof(buf)-1, "unable to create new socket: %s", strerror(errno));
|
@@ -1206,7 +1224,7 @@ const unsigned long EventMachine_t::ConnectToServer (const char *bind_addr, int
|
|
1206
1224
|
}
|
1207
1225
|
}
|
1208
1226
|
|
1209
|
-
|
1227
|
+
uintptr_t out = 0;
|
1210
1228
|
int e = 0;
|
1211
1229
|
|
1212
1230
|
#ifdef OS_UNIX
|
@@ -1326,7 +1344,7 @@ const unsigned long EventMachine_t::ConnectToServer (const char *bind_addr, int
|
|
1326
1344
|
EventMachine_t::ConnectToUnixServer
|
1327
1345
|
***********************************/
|
1328
1346
|
|
1329
|
-
const
|
1347
|
+
const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server)
|
1330
1348
|
{
|
1331
1349
|
/* Connect to a Unix-domain server, which by definition is running
|
1332
1350
|
* on the same host.
|
@@ -1343,7 +1361,7 @@ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
|
|
1343
1361
|
// The whole rest of this function is only compiled on Unix systems.
|
1344
1362
|
#ifdef OS_UNIX
|
1345
1363
|
|
1346
|
-
|
1364
|
+
uintptr_t out = 0;
|
1347
1365
|
|
1348
1366
|
if (!server || !*server)
|
1349
1367
|
return 0;
|
@@ -1360,7 +1378,7 @@ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
|
|
1360
1378
|
|
1361
1379
|
strcpy (pun.sun_path, server);
|
1362
1380
|
|
1363
|
-
int fd =
|
1381
|
+
int fd = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
|
1364
1382
|
if (fd == INVALID_SOCKET)
|
1365
1383
|
return 0;
|
1366
1384
|
|
@@ -1399,7 +1417,7 @@ const unsigned long EventMachine_t::ConnectToUnixServer (const char *server)
|
|
1399
1417
|
EventMachine_t::AttachFD
|
1400
1418
|
************************/
|
1401
1419
|
|
1402
|
-
const
|
1420
|
+
const uintptr_t EventMachine_t::AttachFD (int fd, bool watch_mode)
|
1403
1421
|
{
|
1404
1422
|
#ifdef OS_UNIX
|
1405
1423
|
if (fcntl(fd, F_GETFL, 0) < 0)
|
@@ -1442,7 +1460,7 @@ const unsigned long EventMachine_t::AttachFD (int fd, bool watch_mode)
|
|
1442
1460
|
|
1443
1461
|
Add (cd);
|
1444
1462
|
|
1445
|
-
const
|
1463
|
+
const uintptr_t out = cd->GetBinding();
|
1446
1464
|
return out;
|
1447
1465
|
}
|
1448
1466
|
|
@@ -1458,7 +1476,7 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
|
|
1458
1476
|
int fd = ed->GetSocket();
|
1459
1477
|
|
1460
1478
|
#ifdef HAVE_EPOLL
|
1461
|
-
if (
|
1479
|
+
if (Poller == Poller_Epoll) {
|
1462
1480
|
if (ed->GetSocket() != INVALID_SOCKET) {
|
1463
1481
|
assert (epfd != -1);
|
1464
1482
|
int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
|
@@ -1473,7 +1491,7 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
|
|
1473
1491
|
#endif
|
1474
1492
|
|
1475
1493
|
#ifdef HAVE_KQUEUE
|
1476
|
-
if (
|
1494
|
+
if (Poller == Poller_Kqueue) {
|
1477
1495
|
// remove any read/write events for this fd
|
1478
1496
|
struct kevent k;
|
1479
1497
|
#ifdef __NetBSD__
|
@@ -1579,7 +1597,7 @@ struct sockaddr *name2address (const char *server, int port, int *family, int *b
|
|
1579
1597
|
EventMachine_t::CreateTcpServer
|
1580
1598
|
*******************************/
|
1581
1599
|
|
1582
|
-
const
|
1600
|
+
const uintptr_t EventMachine_t::CreateTcpServer (const char *server, int port)
|
1583
1601
|
{
|
1584
1602
|
/* Create a TCP-acceptor (server) socket and add it to the event machine.
|
1585
1603
|
* Return the binding of the new acceptor to the caller.
|
@@ -1595,7 +1613,7 @@ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int por
|
|
1595
1613
|
|
1596
1614
|
//struct sockaddr_in sin;
|
1597
1615
|
|
1598
|
-
int sd_accept =
|
1616
|
+
int sd_accept = EmSocket (family, SOCK_STREAM, 0);
|
1599
1617
|
if (sd_accept == INVALID_SOCKET) {
|
1600
1618
|
goto fail;
|
1601
1619
|
}
|
@@ -1642,11 +1660,11 @@ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int por
|
|
1642
1660
|
EventMachine_t::OpenDatagramSocket
|
1643
1661
|
**********************************/
|
1644
1662
|
|
1645
|
-
const
|
1663
|
+
const uintptr_t EventMachine_t::OpenDatagramSocket (const char *address, int port)
|
1646
1664
|
{
|
1647
|
-
|
1665
|
+
uintptr_t output_binding = 0;
|
1648
1666
|
|
1649
|
-
int sd =
|
1667
|
+
int sd = EmSocket (AF_INET, SOCK_DGRAM, 0);
|
1650
1668
|
if (sd == INVALID_SOCKET)
|
1651
1669
|
goto fail;
|
1652
1670
|
// from here on, early returns must close the socket!
|
@@ -1717,10 +1735,10 @@ void EventMachine_t::Add (EventableDescriptor *ed)
|
|
1717
1735
|
EventMachine_t::ArmKqueueWriter
|
1718
1736
|
*******************************/
|
1719
1737
|
|
1738
|
+
#ifdef HAVE_KQUEUE
|
1720
1739
|
void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed)
|
1721
1740
|
{
|
1722
|
-
|
1723
|
-
if (bKqueue) {
|
1741
|
+
if (Poller == Poller_Kqueue) {
|
1724
1742
|
if (!ed)
|
1725
1743
|
throw std::runtime_error ("added bad descriptor");
|
1726
1744
|
struct kevent k;
|
@@ -1736,17 +1754,19 @@ void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed)
|
|
1736
1754
|
throw std::runtime_error (buf);
|
1737
1755
|
}
|
1738
1756
|
}
|
1739
|
-
#endif
|
1740
1757
|
}
|
1758
|
+
#else
|
1759
|
+
void EventMachine_t::ArmKqueueWriter (EventableDescriptor *ed UNUSED) { }
|
1760
|
+
#endif
|
1741
1761
|
|
1742
1762
|
/*******************************
|
1743
1763
|
EventMachine_t::ArmKqueueReader
|
1744
1764
|
*******************************/
|
1745
1765
|
|
1766
|
+
#ifdef HAVE_KQUEUE
|
1746
1767
|
void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed)
|
1747
1768
|
{
|
1748
|
-
|
1749
|
-
if (bKqueue) {
|
1769
|
+
if (Poller == Poller_Kqueue) {
|
1750
1770
|
if (!ed)
|
1751
1771
|
throw std::runtime_error ("added bad descriptor");
|
1752
1772
|
struct kevent k;
|
@@ -1762,8 +1782,10 @@ void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed)
|
|
1762
1782
|
throw std::runtime_error (buf);
|
1763
1783
|
}
|
1764
1784
|
}
|
1765
|
-
#endif
|
1766
1785
|
}
|
1786
|
+
#else
|
1787
|
+
void EventMachine_t::ArmKqueueReader (EventableDescriptor *ed UNUSED) { }
|
1788
|
+
#endif
|
1767
1789
|
|
1768
1790
|
/**********************************
|
1769
1791
|
EventMachine_t::_AddNewDescriptors
|
@@ -1788,7 +1810,7 @@ void EventMachine_t::_AddNewDescriptors()
|
|
1788
1810
|
throw std::runtime_error ("adding bad descriptor");
|
1789
1811
|
|
1790
1812
|
#if HAVE_EPOLL
|
1791
|
-
if (
|
1813
|
+
if (Poller == Poller_Epoll) {
|
1792
1814
|
assert (epfd != -1);
|
1793
1815
|
int e = epoll_ctl (epfd, EPOLL_CTL_ADD, ed->GetSocket(), ed->GetEpollEvent());
|
1794
1816
|
if (e) {
|
@@ -1801,7 +1823,7 @@ void EventMachine_t::_AddNewDescriptors()
|
|
1801
1823
|
|
1802
1824
|
#if HAVE_KQUEUE
|
1803
1825
|
/*
|
1804
|
-
if (
|
1826
|
+
if (Poller == Poller_Kqueue) {
|
1805
1827
|
// INCOMPLETE. Some descriptors don't want to be readable.
|
1806
1828
|
assert (kqfd != -1);
|
1807
1829
|
struct kevent k;
|
@@ -1847,7 +1869,7 @@ void EventMachine_t::_ModifyDescriptors()
|
|
1847
1869
|
*/
|
1848
1870
|
|
1849
1871
|
#ifdef HAVE_EPOLL
|
1850
|
-
if (
|
1872
|
+
if (Poller == Poller_Epoll) {
|
1851
1873
|
set<EventableDescriptor*>::iterator i = ModifiedDescriptors.begin();
|
1852
1874
|
while (i != ModifiedDescriptors.end()) {
|
1853
1875
|
assert (*i);
|
@@ -1857,6 +1879,18 @@ void EventMachine_t::_ModifyDescriptors()
|
|
1857
1879
|
}
|
1858
1880
|
#endif
|
1859
1881
|
|
1882
|
+
#ifdef HAVE_KQUEUE
|
1883
|
+
if (Poller == Poller_Kqueue) {
|
1884
|
+
set<EventableDescriptor*>::iterator i = ModifiedDescriptors.begin();
|
1885
|
+
while (i != ModifiedDescriptors.end()) {
|
1886
|
+
assert (*i);
|
1887
|
+
if ((*i)->GetKqueueArmWrite())
|
1888
|
+
ArmKqueueWriter (*i);
|
1889
|
+
++i;
|
1890
|
+
}
|
1891
|
+
}
|
1892
|
+
#endif
|
1893
|
+
|
1860
1894
|
ModifiedDescriptors.clear();
|
1861
1895
|
}
|
1862
1896
|
|
@@ -1885,7 +1919,7 @@ void EventMachine_t::Deregister (EventableDescriptor *ed)
|
|
1885
1919
|
// cut/paste from _CleanupSockets(). The error handling could be
|
1886
1920
|
// refactored out of there, but it is cut/paste all over the
|
1887
1921
|
// file already.
|
1888
|
-
if (
|
1922
|
+
if (Poller == Poller_Epoll) {
|
1889
1923
|
assert (epfd != -1);
|
1890
1924
|
assert (ed->GetSocket() != INVALID_SOCKET);
|
1891
1925
|
int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
|
@@ -1905,7 +1939,7 @@ void EventMachine_t::Deregister (EventableDescriptor *ed)
|
|
1905
1939
|
EventMachine_t::CreateUnixDomainServer
|
1906
1940
|
**************************************/
|
1907
1941
|
|
1908
|
-
const
|
1942
|
+
const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename)
|
1909
1943
|
{
|
1910
1944
|
/* Create a UNIX-domain acceptor (server) socket and add it to the event machine.
|
1911
1945
|
* Return the binding of the new acceptor to the caller.
|
@@ -1923,7 +1957,7 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
|
|
1923
1957
|
|
1924
1958
|
struct sockaddr_un s_sun;
|
1925
1959
|
|
1926
|
-
int sd_accept =
|
1960
|
+
int sd_accept = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
|
1927
1961
|
if (sd_accept == INVALID_SOCKET) {
|
1928
1962
|
goto fail;
|
1929
1963
|
}
|
@@ -1971,9 +2005,9 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
|
|
1971
2005
|
EventMachine_t::AttachSD
|
1972
2006
|
**************************************/
|
1973
2007
|
|
1974
|
-
const
|
2008
|
+
const uintptr_t EventMachine_t::AttachSD (int sd_accept)
|
1975
2009
|
{
|
1976
|
-
|
2010
|
+
uintptr_t output_binding = 0;
|
1977
2011
|
|
1978
2012
|
{
|
1979
2013
|
// Set the acceptor non-blocking.
|
@@ -2006,7 +2040,7 @@ const unsigned long EventMachine_t::AttachSD (int sd_accept)
|
|
2006
2040
|
EventMachine_t::Socketpair
|
2007
2041
|
**************************/
|
2008
2042
|
|
2009
|
-
const
|
2043
|
+
const uintptr_t EventMachine_t::Socketpair (char * const*cmd_strings)
|
2010
2044
|
{
|
2011
2045
|
#ifdef OS_WIN32
|
2012
2046
|
throw std::runtime_error ("socketpair is currently unavailable on this platform");
|
@@ -2024,7 +2058,7 @@ const unsigned long EventMachine_t::Socketpair (char * const*cmd_strings)
|
|
2024
2058
|
if ((j==0) || (j==2048))
|
2025
2059
|
return 0;
|
2026
2060
|
|
2027
|
-
|
2061
|
+
uintptr_t output_binding = 0;
|
2028
2062
|
|
2029
2063
|
int sv[2];
|
2030
2064
|
if (socketpair (AF_LOCAL, SOCK_STREAM, 0, sv) < 0)
|
@@ -2070,7 +2104,7 @@ const unsigned long EventMachine_t::Socketpair (char * const*cmd_strings)
|
|
2070
2104
|
EventMachine_t::OpenKeyboard
|
2071
2105
|
****************************/
|
2072
2106
|
|
2073
|
-
const
|
2107
|
+
const uintptr_t EventMachine_t::OpenKeyboard()
|
2074
2108
|
{
|
2075
2109
|
KeyboardDescriptor *kd = new KeyboardDescriptor (this);
|
2076
2110
|
if (!kd)
|
@@ -2094,10 +2128,10 @@ int EventMachine_t::GetConnectionCount ()
|
|
2094
2128
|
EventMachine_t::WatchPid
|
2095
2129
|
************************/
|
2096
2130
|
|
2097
|
-
|
2131
|
+
#ifdef HAVE_KQUEUE
|
2132
|
+
const uintptr_t EventMachine_t::WatchPid (int pid)
|
2098
2133
|
{
|
2099
|
-
|
2100
|
-
if (!bKqueue)
|
2134
|
+
if (Poller != Poller_Kqueue)
|
2101
2135
|
throw std::runtime_error("must enable kqueue (EM.kqueue=true) for pid watching support");
|
2102
2136
|
|
2103
2137
|
struct kevent event;
|
@@ -2112,17 +2146,17 @@ const unsigned long EventMachine_t::WatchPid (int pid)
|
|
2112
2146
|
sprintf(errbuf, "failed to register file watch descriptor with kqueue: %s", strerror(errno));
|
2113
2147
|
throw std::runtime_error(errbuf);
|
2114
2148
|
}
|
2115
|
-
#endif
|
2116
|
-
|
2117
|
-
#ifdef HAVE_KQUEUE
|
2118
2149
|
Bindable_t* b = new Bindable_t();
|
2119
2150
|
Pids.insert(make_pair (pid, b));
|
2120
2151
|
|
2121
2152
|
return b->GetBinding();
|
2122
|
-
|
2123
|
-
|
2153
|
+
}
|
2154
|
+
#else
|
2155
|
+
const uintptr_t EventMachine_t::WatchPid (int pid UNUSED)
|
2156
|
+
{
|
2124
2157
|
throw std::runtime_error("no pid watching support on this system");
|
2125
2158
|
}
|
2159
|
+
#endif
|
2126
2160
|
|
2127
2161
|
/**************************
|
2128
2162
|
EventMachine_t::UnwatchPid
|
@@ -2148,7 +2182,7 @@ void EventMachine_t::UnwatchPid (int pid)
|
|
2148
2182
|
delete b;
|
2149
2183
|
}
|
2150
2184
|
|
2151
|
-
void EventMachine_t::UnwatchPid (const
|
2185
|
+
void EventMachine_t::UnwatchPid (const uintptr_t sig)
|
2152
2186
|
{
|
2153
2187
|
for(map<int, Bindable_t*>::iterator i=Pids.begin(); i != Pids.end(); i++)
|
2154
2188
|
{
|
@@ -2166,7 +2200,7 @@ void EventMachine_t::UnwatchPid (const unsigned long sig)
|
|
2166
2200
|
EventMachine_t::WatchFile
|
2167
2201
|
*************************/
|
2168
2202
|
|
2169
|
-
const
|
2203
|
+
const uintptr_t EventMachine_t::WatchFile (const char *fpath)
|
2170
2204
|
{
|
2171
2205
|
struct stat sb;
|
2172
2206
|
int sres;
|
@@ -2197,7 +2231,7 @@ const unsigned long EventMachine_t::WatchFile (const char *fpath)
|
|
2197
2231
|
#endif
|
2198
2232
|
|
2199
2233
|
#ifdef HAVE_KQUEUE
|
2200
|
-
if (
|
2234
|
+
if (Poller != Poller_Kqueue)
|
2201
2235
|
throw std::runtime_error("must enable kqueue (EM.kqueue=true) for file watching support");
|
2202
2236
|
|
2203
2237
|
// With kqueue we have to open the file first and use the resulting fd to register for events
|
@@ -2244,7 +2278,7 @@ void EventMachine_t::UnwatchFile (int wd)
|
|
2244
2278
|
delete b;
|
2245
2279
|
}
|
2246
2280
|
|
2247
|
-
void EventMachine_t::UnwatchFile (const
|
2281
|
+
void EventMachine_t::UnwatchFile (const uintptr_t sig)
|
2248
2282
|
{
|
2249
2283
|
for(map<int, Bindable_t*>::iterator i=Files.begin(); i != Files.end(); i++)
|
2250
2284
|
{
|
@@ -2270,9 +2304,9 @@ void EventMachine_t::_ReadInotifyEvents()
|
|
2270
2304
|
|
2271
2305
|
for (;;) {
|
2272
2306
|
int returned = read(inotify->GetSocket(), buffer, sizeof(buffer));
|
2273
|
-
assert(!(returned == 0 || returned == -1 && errno == EINVAL));
|
2307
|
+
assert(!(returned == 0 || (returned == -1 && errno == EINVAL)));
|
2274
2308
|
if (returned <= 0) {
|
2275
|
-
|
2309
|
+
break;
|
2276
2310
|
}
|
2277
2311
|
int current = 0;
|
2278
2312
|
while (current < returned) {
|