sensu-em 2.4.1-java → 2.5.0.beta-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) 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/lib/rubyeventmachine.jar +0 -0
  30. data/rakelib/package.rake +1 -1
  31. data/tests/em_test_helper.rb +4 -0
  32. data/tests/test_attach.rb +1 -0
  33. data/tests/test_basic.rb +14 -16
  34. data/tests/test_completion.rb +1 -0
  35. data/tests/test_connection_count.rb +1 -0
  36. data/tests/test_connection_write.rb +35 -0
  37. data/tests/test_epoll.rb +11 -14
  38. data/tests/test_httpclient.rb +43 -0
  39. data/tests/test_iterator.rb +6 -6
  40. data/tests/test_kb.rb +19 -25
  41. data/tests/test_many_fds.rb +22 -0
  42. data/tests/test_pause.rb +7 -2
  43. data/tests/test_pool.rb +2 -0
  44. data/tests/test_process_watch.rb +2 -0
  45. data/tests/test_processes.rb +7 -7
  46. data/tests/test_resolver.rb +33 -7
  47. data/tests/test_ssl_methods.rb +3 -4
  48. data/tests/test_ssl_verify.rb +62 -62
  49. data/tests/test_threaded_resource.rb +8 -0
  50. data/tmp/java/rubyeventmachine/.build +0 -0
  51. metadata +27 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d02036176fdcb5e9afe3b5231109fb088a4969d5
4
- data.tar.gz: 5fe622e3a485c9068f85880848c0c8ae2c28c9df
3
+ metadata.gz: 9cd81577274ffb873588073417aef55f93f6a76f
4
+ data.tar.gz: bdca94e3528cfd4790448a60c20a1398d696900b
5
5
  SHA512:
6
- metadata.gz: db0093bf36a2b276c2eb78793e3c44b945dfc93e42b0d8de18d597a05bd447ef1dd6a00d8df8065e25363d143f38ccd956058fd215aeb7a3ed1b2f2feece0224
7
- data.tar.gz: 5aceb1eb85e1c2613ef4cb3c4ec70d5c47e190f6dfccebdca4058b1ed9b8df6f6064240193f2e4161491a81786bce16dca833ab66b85589abb1cb9cd0e41b113
6
+ metadata.gz: 643200d1b2e606a478277ae4752fa3f73a240df8d7c077ff6c82160332d73a0d254a284f6c6d5d2e1dd5a8b32cde04eaf34ad5abc7912fb93d21b95bcf6be7ab
7
+ data.tar.gz: 2cd5177c480850136024b7bf6f455b4c1c065454b845ccdb8aa644d2bf82fc7c44a2223b1b02a9168e1bcb0b590f2c5f67eaf4087035254b614bef39bbd81079
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
-