sensu-em 2.4.1 → 2.5.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +15 -5
  3. data/CHANGELOG.md +41 -1
  4. data/README.md +2 -3
  5. data/eventmachine.gemspec +2 -1
  6. data/ext/cmain.cpp +19 -3
  7. data/ext/ed.cpp +22 -8
  8. data/ext/em.cpp +123 -76
  9. data/ext/em.h +40 -6
  10. data/ext/eventmachine.h +2 -0
  11. data/ext/extconf.rb +16 -2
  12. data/ext/fastfilereader/extconf.rb +3 -0
  13. data/ext/fastfilereader/mapper.cpp +1 -1
  14. data/ext/project.h +11 -7
  15. data/ext/rubymain.cpp +38 -2
  16. data/ext/ssl.cpp +4 -1
  17. data/ext/ssl.h +4 -0
  18. data/java/src/com/rubyeventmachine/EventableChannel.java +8 -1
  19. data/lib/em/buftok.rb +34 -85
  20. data/lib/em/protocols/httpclient.rb +31 -11
  21. data/lib/em/protocols/line_and_text.rb +2 -3
  22. data/lib/em/protocols/linetext2.rb +0 -1
  23. data/lib/em/protocols/smtpserver.rb +32 -9
  24. data/lib/em/pure_ruby.rb +2 -2
  25. data/lib/em/tick_loop.rb +19 -19
  26. data/lib/em/version.rb +1 -1
  27. data/lib/eventmachine.rb +12 -4
  28. data/lib/jeventmachine.rb +22 -6
  29. data/rakelib/package.rake +1 -1
  30. data/tests/em_test_helper.rb +4 -0
  31. data/tests/test_attach.rb +1 -0
  32. data/tests/test_basic.rb +14 -16
  33. data/tests/test_completion.rb +1 -0
  34. data/tests/test_connection_count.rb +1 -0
  35. data/tests/test_connection_write.rb +35 -0
  36. data/tests/test_epoll.rb +11 -14
  37. data/tests/test_httpclient.rb +43 -0
  38. data/tests/test_iterator.rb +6 -6
  39. data/tests/test_kb.rb +19 -25
  40. data/tests/test_many_fds.rb +22 -0
  41. data/tests/test_pause.rb +7 -2
  42. data/tests/test_pool.rb +2 -0
  43. data/tests/test_process_watch.rb +2 -0
  44. data/tests/test_processes.rb +7 -7
  45. data/tests/test_resolver.rb +33 -7
  46. data/tests/test_ssl_methods.rb +3 -4
  47. data/tests/test_ssl_verify.rb +62 -62
  48. data/tests/test_threaded_resource.rb +8 -0
  49. data/tmp/java/rubyeventmachine/.build +0 -0
  50. metadata +21 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b96bf3888d5f207e1510d20bb81790e84b2d1180
4
- data.tar.gz: 2b478bee9b3e1108511f8238e889d4ad3f32b9ec
3
+ metadata.gz: 52263bd3723537a9a721e556dd5516e9cda1fee7
4
+ data.tar.gz: ee762853b84222141bc65da790af811eaf914cb8
5
5
  SHA512:
6
- metadata.gz: bbfb7462ffadc0c5447e349bc4e5b7233832421099c8f194d8244f9a2059b922cf9618dd3cb648a8c5ef4f2978d84d46ad16dbc8371ba55ec0b1baa445c3bf92
7
- data.tar.gz: b7c4945f38bf515f30ac6ff89ea5210282c1064ceb8804507a618ae756ac7d5a3a257fde382b8123dee5f3fddf586c9f7b1c92b7be33573d041f641ea53f31a7
6
+ metadata.gz: c23f57da24c2c4b6da1fdb2b1e6fb76b6defc6738bef5bbdbda6b123e879445db1b78db18aa7f73cda65dfd99d656dc4f2b54c3586b80eb504ffbdbc42ea2aef
7
+ data.tar.gz: e9265b41b73569cf3a61714380cd9de97c2a81e1d9c7438e77b4c27b572f19eda138503dbde7976a5b48f78f423d211c7411b98b261535e9cbf6d864f55facd4
data/.travis.yml CHANGED
@@ -1,12 +1,22 @@
1
- script: rake compile test
1
+ script: bundle exec rake compile test
2
+ env:
3
+ global:
4
+ - TESTOPTS=-v
2
5
  language: ruby
6
+ sudo: false
3
7
  rvm:
4
8
  - 1.8.7
9
+ - 1.9.2
5
10
  - 1.9.3
6
- - rbx-18mode
7
- - rbx-19mode
11
+ - 2.0.0
12
+ - 2.1
13
+ - 2.2
14
+ - rbx
8
15
  - jruby
9
16
  matrix:
10
17
  allow_failures:
11
- - rvm: rbx-18mode
12
- - rvm: rbx-19mode
18
+ - rvm: rbx
19
+ - rvm: jruby
20
+ include:
21
+ - rvm: 2.0.0
22
+ os: osx
data/CHANGELOG.md CHANGED
@@ -1,6 +1,46 @@
1
1
  # Changelog
2
2
 
3
- ## 1.0.4
3
+ ## 1.0.7 (February 10, 2015)
4
+ * fix delay in kqueue/epoll reactor shutdown when timers exist [#587]
5
+ * fix memory leak introduced in v1.0.5 [#586]
6
+ * expose EM.set_simultaneous_accept_count [#420]
7
+ * fix busy loop when EM.run and EM.next_tick are invoked from exception handler [#452]
8
+
9
+ ## 1.0.6 (February 3, 2015)
10
+ * add support for Rubinius Process::Status [#568]
11
+ * small bugfixes for SmtpServer [#449]
12
+ * update buftok.rb [#547]
13
+ * fix assertion on Write() [#525]
14
+ * work around mkmf.rb bug preventing gem installation [#574]
15
+ * add pause/resume support to jruby reactor [#556]
16
+ * fix pure ruby reactor to use 127.0.0.1 instead of localhost [#439]
17
+ * fix compilation under macruby [#243]
18
+ * add chunked encoding to http client [#111]
19
+ * fix errors on win32 when dealing with pipes [1ea45498] [#105]
20
+
21
+ ## 1.0.5 (February 2, 2015)
22
+ * use monotonic clocks on Linux, OS X, Solaris, and Windows [#563]
23
+ * use the rb_fd_* API to get autosized fd_sets [#502]
24
+ * add basic tests that the DNS resolver isn't leaking timers [#571]
25
+ * update to test-unit 2.x and improve various unit tests [#551]
26
+ * remove EventMachine_t::Popen code marked by ifdef OBSOLETE [#551]
27
+ * ruby 2.0 may fail at Queue.pop, so rescue and complain to $stderr [#551]
28
+ * set file handle to INVALID_HANDLE_VALUE after closing the file [#565]
29
+ * use `defined?` instead of rescuing NameError for flow control [#535]
30
+ * fix closing files and sockets on Windows [#564]
31
+ * fix file uploads in Windows [#562]
32
+ * catch failure to fork [#539]
33
+ * use chunks for SSL write [#545]
34
+
35
+ ## 1.0.4 (December 19, 2014)
36
+ * add starttls_options to smtp server [#552]
37
+ * fix closesocket on windows [#497]
38
+ * fix build on ruby 2.2 [#503]
39
+ * fix build error on ruby 1.9 [#508]
40
+ * fix timer leak during dns resolution [#489]
41
+ * add concurrency validation to EM::Iterator [#468]
42
+ * add get_file_descriptor to get fd for a signature [#467]
43
+ * add EM.attach_server and EM.attach_socket_server [#465, #466]
4
44
  * calling pause from receive_data takes effect immediately [#464]
5
45
  * reactor_running? returns false after fork [#455]
6
46
  * fix infinite loop on double close [edc4d0e6, #441, #445]
data/README.md CHANGED
@@ -86,7 +86,7 @@ Here's a fully-functional echo server written with EventMachine:
86
86
 
87
87
  ## EventMachine documentation ##
88
88
 
89
- Currently we only have [reference documentation](http://eventmachine.rubyforge.org) and a [wiki](https://github.com/eventmachine/eventmachine/wiki).
89
+ Currently we only have [reference documentation](http://rdoc.info/github/eventmachine/eventmachine/frames) and a [wiki](https://github.com/eventmachine/eventmachine/wiki).
90
90
 
91
91
 
92
92
  ## Community and where to get help ##
@@ -105,5 +105,4 @@ Copyright: (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
105
105
 
106
106
  ## Alternatives ##
107
107
 
108
- If you are unhappy with EventMachine and want to use Ruby, check out [Cool.io](http://coolio.github.com/).
109
- One caveat: by May 2011, it did not support JRuby and Windows.
108
+ If you are unhappy with EventMachine and want to use Ruby, check out [Celluloid](https://celluloid.io/).
data/eventmachine.gemspec CHANGED
@@ -5,7 +5,7 @@ require "em/version"
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = 'sensu-em'
8
- s.version = '2.4.1'
8
+ s.version = '2.5.0.beta'
9
9
  s.homepage = 'http://rubyeventmachine.com'
10
10
  s.rubyforge_project = 'eventmachine'
11
11
  s.licenses = ["Ruby", "GPL"]
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.files = `git ls-files`.split("\n")
17
17
  s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
18
18
 
19
+ s.add_development_dependency 'test-unit', '~> 2.0'
19
20
  s.add_development_dependency 'rake-compiler', '~> 0.8.3'
20
21
  s.add_development_dependency 'yard', ">= 0.8.5.2"
21
22
  s.add_development_dependency 'bluecloth' unless RUBY_PLATFORM =~ /java/
data/ext/cmain.cpp CHANGED
@@ -653,7 +653,6 @@ extern "C" int evma_get_max_timer_count()
653
653
  return EventMachine_t::GetMaxTimerCount();
654
654
  }
655
655
 
656
-
657
656
  /************************
658
657
  evma_set_max_timer_count
659
658
  ************************/
@@ -671,6 +670,21 @@ extern "C" void evma_set_max_timer_count (int ct)
671
670
  EventMachine_t::SetMaxTimerCount (ct);
672
671
  }
673
672
 
673
+ /******************
674
+ evma_get/set_simultaneous_accept_count
675
+ ******************/
676
+
677
+ extern "C" void evma_set_simultaneous_accept_count (int count)
678
+ {
679
+ EventMachine_t::SetSimultaneousAcceptCount(count);
680
+ }
681
+
682
+ extern "C" int evma_get_simultaneous_accept_count()
683
+ {
684
+ return EventMachine_t::GetSimultaneousAcceptCount();
685
+ }
686
+
687
+
674
688
  /******************
675
689
  evma_setuid_string
676
690
  ******************/
@@ -762,8 +776,11 @@ extern "C" int evma_send_file_data_to_connection (const unsigned long binding, c
762
776
 
763
777
  ensure_eventmachine("evma_send_file_data_to_connection");
764
778
 
779
+ #if defined(OS_WIN32)
780
+ int Fd = open (filename, O_RDONLY|O_BINARY);
781
+ #else
765
782
  int Fd = open (filename, O_RDONLY);
766
-
783
+ #endif
767
784
  if (Fd < 0)
768
785
  return errno;
769
786
  // From here on, all early returns MUST close Fd.
@@ -785,7 +802,6 @@ extern "C" int evma_send_file_data_to_connection (const unsigned long binding, c
785
802
  return -1;
786
803
  }
787
804
 
788
-
789
805
  r = read (Fd, data, filesize);
790
806
  if (r != filesize) {
791
807
  int e = errno;
data/ext/ed.cpp CHANGED
@@ -567,11 +567,25 @@ int ConnectionDescriptor::SendOutboundData (const char *data, int length)
567
567
  #ifdef WITH_SSL
568
568
  if (SslBox) {
569
569
  if (length > 0) {
570
- int w = SslBox->PutPlaintext (data, length);
571
- if (w < 0)
572
- ScheduleClose (false);
573
- else
574
- _DispatchCiphertext();
570
+ int writed = 0;
571
+ char *p = (char*)data;
572
+
573
+ while (writed < length) {
574
+ int to_write = SSLBOX_INPUT_CHUNKSIZE;
575
+ int remaining = length - writed;
576
+
577
+ if (remaining < SSLBOX_INPUT_CHUNKSIZE)
578
+ to_write = remaining;
579
+
580
+ int w = SslBox->PutPlaintext (p, to_write);
581
+ if (w < 0) {
582
+ ScheduleClose (false);
583
+ }else
584
+ _DispatchCiphertext();
585
+
586
+ p += to_write;
587
+ writed += to_write;
588
+ }
575
589
  }
576
590
  // TODO: What's the correct return value?
577
591
  return 1; // That's a wild guess, almost certainly wrong.
@@ -603,7 +617,6 @@ int ConnectionDescriptor::_SendRawOutboundData (const char *data, int length)
603
617
 
604
618
  if (IsCloseScheduled())
605
619
  return 0;
606
-
607
620
  // 25Mar10: Ignore 0 length packets as they are not meaningful in TCP (as opposed to UDP)
608
621
  // and can cause the assert(nbytes>0) to fail when OutboundPages has a bunch of 0 length pages.
609
622
  if (length == 0)
@@ -1230,7 +1243,7 @@ void ConnectionDescriptor::_DispatchCiphertext()
1230
1243
  assert (SslBox);
1231
1244
 
1232
1245
 
1233
- char BigBuf [2048];
1246
+ char BigBuf [SSLBOX_OUTPUT_CHUNKSIZE];
1234
1247
  bool did_work;
1235
1248
 
1236
1249
  do {
@@ -1422,8 +1435,9 @@ void AcceptorDescriptor::Read()
1422
1435
 
1423
1436
  struct sockaddr_in pin;
1424
1437
  socklen_t addrlen = sizeof (pin);
1438
+ int accept_count = EventMachine_t::GetSimultaneousAcceptCount();
1425
1439
 
1426
- for (int i=0; i < 10; i++) {
1440
+ for (int i=0; i < accept_count; i++) {
1427
1441
  int sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
1428
1442
  if (sd == INVALID_SOCKET) {
1429
1443
  // This breaks the loop when we've accepted everything on the kernel queue,
data/ext/em.cpp CHANGED
@@ -27,6 +27,11 @@ See the file COPYING for complete licensing information.
27
27
  */
28
28
  static unsigned int MaxOutstandingTimers = 100000;
29
29
 
30
+ /* The number of accept() done at once in a single tick when the acceptor
31
+ * socket becomes readable.
32
+ */
33
+ static unsigned int SimultaneousAcceptCount = 10;
34
+
30
35
 
31
36
  /* Internal helper to convert strings to internet addresses. IPv6-aware.
32
37
  * Not reentrant or threadsafe, optimized for speed.
@@ -61,6 +66,17 @@ void EventMachine_t::SetMaxTimerCount (int count)
61
66
  MaxOutstandingTimers = count;
62
67
  }
63
68
 
69
+ int EventMachine_t::GetSimultaneousAcceptCount()
70
+ {
71
+ return SimultaneousAcceptCount;
72
+ }
73
+
74
+ void EventMachine_t::SetSimultaneousAcceptCount (int count)
75
+ {
76
+ if (count < 1)
77
+ count = 1;
78
+ SimultaneousAcceptCount = count;
79
+ }
64
80
 
65
81
 
66
82
  /******************************
@@ -68,12 +84,12 @@ EventMachine_t::EventMachine_t
68
84
  ******************************/
69
85
 
70
86
  EventMachine_t::EventMachine_t (EMCallback event_callback):
87
+ NumCloseScheduled (0),
71
88
  HeartbeatInterval(2000000),
72
89
  EventCallback (event_callback),
73
90
  NextHeartbeatTime (0),
74
91
  LoopBreakerReader (-1),
75
92
  LoopBreakerWriter (-1),
76
- NumCloseScheduled (0),
77
93
  bTerminateSignalReceived (false),
78
94
  bEpoll (false),
79
95
  epfd (-1),
@@ -85,6 +101,11 @@ EventMachine_t::EventMachine_t (EMCallback event_callback):
85
101
  Quantum.tv_sec = 0;
86
102
  Quantum.tv_usec = 90000;
87
103
 
104
+ /* Initialize monotonic timekeeping on OS X before the first call to GetRealTime */
105
+ #ifdef OS_DARWIN
106
+ (void) mach_timebase_info(&mach_timebase);
107
+ #endif
108
+
88
109
  // Make sure the current loop time is sane, in case we do any initializations of
89
110
  // objects before we start running.
90
111
  _UpdateTime();
@@ -101,6 +122,7 @@ EventMachine_t::EventMachine_t (EMCallback event_callback):
101
122
  #endif
102
123
 
103
124
  _InitializeLoopBreaker();
125
+ SelectData = new SelectData_t();
104
126
  }
105
127
 
106
128
 
@@ -130,6 +152,8 @@ EventMachine_t::~EventMachine_t()
130
152
  close (epfd);
131
153
  if (kqfd != -1)
132
154
  close (kqfd);
155
+
156
+ delete SelectData;
133
157
  }
134
158
 
135
159
 
@@ -187,6 +211,12 @@ void EventMachine_t::ScheduleHalt()
187
211
  * The answer is to call evma_stop_machine, which calls here, from a SIGINT handler.
188
212
  */
189
213
  bTerminateSignalReceived = true;
214
+
215
+ /* Signal the loopbreaker so we break out of long-running select/epoll/kqueue and
216
+ * notice the halt boolean is set. Signalling the loopbreaker also uses a single
217
+ * signal-safe syscall.
218
+ */
219
+ SignalLoopBreaker();
190
220
  }
191
221
 
192
222
 
@@ -352,16 +382,49 @@ void EventMachine_t::_UpdateTime()
352
382
  EventMachine_t::GetRealTime
353
383
  ***************************/
354
384
 
385
+ // Two great writeups of cross-platform monotonic time are at:
386
+ // http://www.python.org/dev/peps/pep-0418
387
+ // http://nadeausoftware.com/articles/2012/04/c_c_tip_how_measure_elapsed_real_time_benchmarking
388
+ // Uncomment the #pragma messages to confirm which compile-time option was used
355
389
  uint64_t EventMachine_t::GetRealTime()
356
390
  {
357
391
  uint64_t current_time;
358
392
 
359
- #if defined(OS_UNIX)
393
+ #if defined(HAVE_CONST_CLOCK_MONOTONIC_RAW)
394
+ // #pragma message "GetRealTime: clock_gettime CLOCK_MONOTONIC_RAW"
395
+ // Linux 2.6.28 and above
396
+ struct timespec tv;
397
+ clock_gettime (CLOCK_MONOTONIC_RAW, &tv);
398
+ current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)((tv.tv_nsec)/1000));
399
+
400
+ #elif defined(HAVE_CONST_CLOCK_MONOTONIC)
401
+ // #pragma message "GetRealTime: clock_gettime CLOCK_MONOTONIC"
402
+ // Linux, FreeBSD 5.0 and above, Solaris 8 and above, OpenBSD, NetBSD, DragonflyBSD
403
+ struct timespec tv;
404
+ clock_gettime (CLOCK_MONOTONIC, &tv);
405
+ current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)((tv.tv_nsec)/1000));
406
+
407
+ #elif defined(HAVE_GETHRTIME)
408
+ // #pragma message "GetRealTime: gethrtime"
409
+ // Solaris and HP-UX
410
+ current_time = (uint64_t)gethrtime() / 1000;
411
+
412
+ #elif defined(OS_DARWIN)
413
+ // #pragma message "GetRealTime: mach_absolute_time"
414
+ // Mac OS X
415
+ // https://developer.apple.com/library/mac/qa/qa1398/_index.html
416
+ current_time = mach_absolute_time() * mach_timebase.numer / mach_timebase.denom / 1000;
417
+
418
+ #elif defined(OS_UNIX)
419
+ // #pragma message "GetRealTime: gettimeofday"
420
+ // Unix fallback
360
421
  struct timeval tv;
361
422
  gettimeofday (&tv, NULL);
362
423
  current_time = (((uint64_t)(tv.tv_sec)) * 1000000LL) + ((uint64_t)(tv.tv_usec));
363
424
 
364
425
  #elif defined(OS_WIN32)
426
+ // #pragma message "GetRealTime: GetTickCount"
427
+ // Future improvement: use GetTickCount64 in Windows Vista / Server 2008
365
428
  unsigned tick = GetTickCount();
366
429
  if (tick < LastTickCount)
367
430
  TickCountTickover += 1;
@@ -370,6 +433,8 @@ uint64_t EventMachine_t::GetRealTime()
370
433
  current_time *= 1000; // convert to microseconds
371
434
 
372
435
  #else
436
+ // #pragma message "GetRealTime: time"
437
+ // Universal fallback
373
438
  current_time = (uint64_t)time(NULL) * 1000000LL;
374
439
  #endif
375
440
 
@@ -806,11 +871,17 @@ SelectData_t::SelectData_t
806
871
  SelectData_t::SelectData_t()
807
872
  {
808
873
  maxsocket = 0;
809
- FD_ZERO (&fdreads);
810
- FD_ZERO (&fdwrites);
811
- FD_ZERO (&fderrors);
874
+ rb_fd_init (&fdreads);
875
+ rb_fd_init (&fdwrites);
876
+ rb_fd_init (&fderrors);
812
877
  }
813
878
 
879
+ SelectData_t::~SelectData_t()
880
+ {
881
+ rb_fd_term (&fdreads);
882
+ rb_fd_term (&fdwrites);
883
+ rb_fd_term (&fderrors);
884
+ }
814
885
 
815
886
  #ifdef BUILD_FOR_RUBY
816
887
  /*****************
@@ -821,7 +892,7 @@ _SelectDataSelect
821
892
  static VALUE _SelectDataSelect (void *v)
822
893
  {
823
894
  SelectData_t *sd = (SelectData_t*)v;
824
- sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
895
+ sd->nSockets = select (sd->maxsocket+1, rb_fd_ptr(&(sd->fdreads)), rb_fd_ptr(&(sd->fdwrites)), rb_fd_ptr(&(sd->fderrors)), &(sd->tv));
825
896
  return Qnil;
826
897
  }
827
898
  #endif
@@ -833,9 +904,11 @@ SelectData_t::_Select
833
904
  int SelectData_t::_Select()
834
905
  {
835
906
  #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
907
+ // added in ruby 1.9.3
836
908
  rb_thread_call_without_gvl ((void *(*)(void *))_SelectDataSelect, (void*)this, RUBY_UBF_IO, 0);
837
909
  return nSockets;
838
910
  #elif defined(HAVE_TBR)
911
+ // added in ruby 1.9.1, deprecated in ruby 2.0.0
839
912
  rb_thread_blocking_region (_SelectDataSelect, (void*)this, RUBY_UBF_IO, 0);
840
913
  return nSockets;
841
914
  #else
@@ -844,7 +917,13 @@ int SelectData_t::_Select()
844
917
  }
845
918
  #endif
846
919
 
847
-
920
+ void SelectData_t::_Clear()
921
+ {
922
+ maxsocket = 0;
923
+ rb_fd_zero (&fdreads);
924
+ rb_fd_zero (&fdwrites);
925
+ rb_fd_zero (&fderrors);
926
+ }
848
927
 
849
928
  /******************************
850
929
  EventMachine_t::_RunSelectOnce
@@ -861,23 +940,17 @@ void EventMachine_t::_RunSelectOnce()
861
940
  // however it has the same problem interoperating with Ruby
862
941
  // threads that select does.
863
942
 
864
- SelectData_t SelectData;
865
- /*
866
- fd_set fdreads, fdwrites;
867
- FD_ZERO (&fdreads);
868
- FD_ZERO (&fdwrites);
869
-
870
- int maxsocket = 0;
871
- */
943
+ // Get ready for select()
944
+ SelectData->_Clear();
872
945
 
873
946
  // Always read the loop-breaker reader.
874
947
  // Changed 23Aug06, provisionally implemented for Windows with a UDP socket
875
948
  // running on localhost with a randomly-chosen port. (*Puke*)
876
949
  // Windows has a version of the Unix pipe() library function, but it doesn't
877
950
  // give you back descriptors that are selectable.
878
- FD_SET (LoopBreakerReader, &(SelectData.fdreads));
879
- if (SelectData.maxsocket < LoopBreakerReader)
880
- SelectData.maxsocket = LoopBreakerReader;
951
+ rb_fd_set (LoopBreakerReader, &(SelectData->fdreads));
952
+ if (SelectData->maxsocket < LoopBreakerReader)
953
+ SelectData->maxsocket = LoopBreakerReader;
881
954
 
882
955
  // prepare the sockets for reading and writing
883
956
  size_t i;
@@ -890,27 +963,28 @@ void EventMachine_t::_RunSelectOnce()
890
963
  assert (sd != INVALID_SOCKET);
891
964
 
892
965
  if (ed->SelectForRead())
893
- FD_SET (sd, &(SelectData.fdreads));
966
+ rb_fd_set (sd, &(SelectData->fdreads));
894
967
  if (ed->SelectForWrite())
895
- FD_SET (sd, &(SelectData.fdwrites));
968
+ rb_fd_set (sd, &(SelectData->fdwrites));
896
969
 
897
970
  #ifdef OS_WIN32
898
971
  /* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
899
972
  Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
900
973
  */
901
- FD_SET (sd, &(SelectData.fderrors));
974
+ if (ed->IsConnectPending())
975
+ rb_fd_set (sd, &(SelectData->fderrors));
902
976
  #endif
903
977
 
904
- if (SelectData.maxsocket < sd)
905
- SelectData.maxsocket = sd;
978
+ if (SelectData->maxsocket < sd)
979
+ SelectData->maxsocket = sd;
906
980
  }
907
981
 
908
982
 
909
983
  { // read and write the sockets
910
984
  //timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000.
911
985
  //timeval tv = Quantum;
912
- SelectData.tv = _TimeTilNextEvent();
913
- int s = SelectData._Select();
986
+ SelectData->tv = _TimeTilNextEvent();
987
+ int s = SelectData->_Select();
914
988
  //rb_thread_blocking_region(xxx,(void*)&SelectData,RUBY_UBF_IO,0);
915
989
  //int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads), &(SelectData.fdwrites), NULL, &(SelectData.tv));
916
990
  //int s = SelectData.nSockets;
@@ -933,15 +1007,19 @@ void EventMachine_t::_RunSelectOnce()
933
1007
  continue;
934
1008
  assert (sd != INVALID_SOCKET);
935
1009
 
936
- if (FD_ISSET (sd, &(SelectData.fdwrites)))
937
- ed->Write();
938
- if (FD_ISSET (sd, &(SelectData.fdreads)))
1010
+ if (rb_fd_isset (sd, &(SelectData->fdwrites))) {
1011
+ // Double-check SelectForWrite() still returns true. If not, one of the callbacks must have
1012
+ // modified some value since we checked SelectForWrite() earlier in this method.
1013
+ if (ed->SelectForWrite())
1014
+ ed->Write();
1015
+ }
1016
+ if (rb_fd_isset (sd, &(SelectData->fdreads)))
939
1017
  ed->Read();
940
- if (FD_ISSET (sd, &(SelectData.fderrors)))
1018
+ if (rb_fd_isset (sd, &(SelectData->fderrors)))
941
1019
  ed->HandleError();
942
1020
  }
943
1021
 
944
- if (FD_ISSET (LoopBreakerReader, &(SelectData.fdreads)))
1022
+ if (rb_fd_isset (LoopBreakerReader, &(SelectData->fdreads)))
945
1023
  _ReadLoopBreaker();
946
1024
  }
947
1025
  else if (s < 0) {
@@ -979,11 +1057,12 @@ void EventMachine_t::_CleanBadDescriptors()
979
1057
  tv.tv_sec = 0;
980
1058
  tv.tv_usec = 0;
981
1059
 
982
- fd_set fds;
983
- FD_ZERO(&fds);
984
- FD_SET(sd, &fds);
1060
+ rb_fdset_t fds;
1061
+ rb_fd_init(&fds);
1062
+ rb_fd_set(sd, &fds);
985
1063
 
986
- int ret = select(sd + 1, &fds, NULL, NULL, &tv);
1064
+ int ret = rb_fd_select(sd + 1, &fds, NULL, NULL, &tv);
1065
+ rb_fd_term(&fds);
987
1066
 
988
1067
  if (ret == -1) {
989
1068
  if (errno == EBADF)
@@ -1600,6 +1679,16 @@ const unsigned long EventMachine_t::OpenDatagramSocket (const char *address, int
1600
1679
  goto fail;
1601
1680
  }
1602
1681
 
1682
+ // Set CLOEXEC. Only makes sense on Unix.
1683
+ {
1684
+ #ifdef OS_UNIX
1685
+ int cloexec = fcntl (sd, F_GETFD, 0);
1686
+ assert (cloexec >= 0);
1687
+ cloexec |= FD_CLOEXEC;
1688
+ fcntl (sd, F_SETFD, cloexec);
1689
+ #endif
1690
+ }
1691
+
1603
1692
  if (bind (sd, (struct sockaddr*)&sin, sizeof(sin)) != 0)
1604
1693
  goto fail;
1605
1694
 
@@ -1923,47 +2012,6 @@ const unsigned long EventMachine_t::AttachSD (int sd_accept)
1923
2012
  }
1924
2013
 
1925
2014
 
1926
- /*********************
1927
- EventMachine_t::Popen
1928
- *********************/
1929
- #if OBSOLETE
1930
- const char *EventMachine_t::Popen (const char *cmd, const char *mode)
1931
- {
1932
- #ifdef OS_WIN32
1933
- throw std::runtime_error ("popen is currently unavailable on this platform");
1934
- #endif
1935
-
1936
- // The whole rest of this function is only compiled on Unix systems.
1937
- // Eventually we need this functionality (or a full-duplex equivalent) on Windows.
1938
- #ifdef OS_UNIX
1939
- const char *output_binding = NULL;
1940
-
1941
- FILE *fp = popen (cmd, mode);
1942
- if (!fp)
1943
- return NULL;
1944
-
1945
- // From here, all early returns must pclose the stream.
1946
-
1947
- // According to the pipe(2) manpage, descriptors returned from pipe have both
1948
- // CLOEXEC and NONBLOCK clear. Do NOT set CLOEXEC. DO set nonblocking.
1949
- if (!SetSocketNonblocking (fileno (fp))) {
1950
- pclose (fp);
1951
- return NULL;
1952
- }
1953
-
1954
- { // Looking good.
1955
- PipeDescriptor *pd = new PipeDescriptor (fp, this);
1956
- if (!pd)
1957
- throw std::runtime_error ("unable to allocate pipe");
1958
- Add (pd);
1959
- output_binding = pd->GetBinding();
1960
- }
1961
-
1962
- return output_binding;
1963
- #endif
1964
- }
1965
- #endif // OBSOLETE
1966
-
1967
2015
  /**************************
1968
2016
  EventMachine_t::Socketpair
1969
2017
  **************************/
@@ -2349,4 +2397,3 @@ int EventMachine_t::SetHeartbeatInterval(float interval)
2349
2397
  return 0;
2350
2398
  }
2351
2399
  //#endif // OS_UNIX
2352
-