sonixlabs-eventmachine-java 1.0.0.rc.7-java → 1.0.3.1-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 (58) hide show
  1. checksums.yaml +4 -12
  2. data/.travis.yml +12 -0
  3. data/CHANGELOG.md +33 -0
  4. data/Gemfile +0 -1
  5. data/README.md +2 -2
  6. data/README_JP.md +10 -2
  7. data/eventmachine.gemspec +10 -7
  8. data/ext/binder.cpp +1 -1
  9. data/ext/cmain.cpp +11 -0
  10. data/ext/ed.cpp +22 -7
  11. data/ext/ed.h +5 -5
  12. data/ext/em.cpp +64 -66
  13. data/ext/em.h +10 -5
  14. data/ext/eventmachine.h +1 -0
  15. data/ext/extconf.rb +4 -3
  16. data/ext/fastfilereader/extconf.rb +1 -1
  17. data/ext/rubymain.cpp +22 -1
  18. data/ext/ssl.cpp +1 -1
  19. data/java/.classpath +1 -3
  20. data/java/.gitignore +1 -0
  21. data/java/src/com/rubyeventmachine/DatagramPacket.java +13 -0
  22. data/java/src/com/rubyeventmachine/EmReactor.java +502 -561
  23. data/java/src/com/rubyeventmachine/EventCallback.java +7 -0
  24. data/java/src/com/rubyeventmachine/EventCode.java +26 -0
  25. data/java/src/com/rubyeventmachine/EventableChannel.java +102 -42
  26. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +146 -161
  27. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +371 -334
  28. data/java/src/com/rubyeventmachine/SslBox.java +310 -0
  29. data/lib/em/iterator.rb +5 -44
  30. data/lib/em/processes.rb +1 -1
  31. data/lib/em/protocols/httpclient.rb +2 -2
  32. data/lib/em/protocols/line_protocol.rb +2 -2
  33. data/lib/em/protocols/smtpclient.rb +1 -1
  34. data/lib/em/protocols/smtpserver.rb +10 -7
  35. data/lib/em/protocols/stomp.rb +5 -2
  36. data/lib/em/protocols.rb +1 -0
  37. data/lib/em/version.rb +1 -1
  38. data/lib/eventmachine.rb +35 -14
  39. data/lib/jeventmachine.rb +65 -18
  40. data/rakelib/package.rake +15 -18
  41. data/tests/server.crt +36 -0
  42. data/tests/server.key +51 -0
  43. data/tests/test_attach.rb +24 -0
  44. data/tests/test_connection_count.rb +21 -1
  45. data/tests/test_epoll.rb +15 -0
  46. data/tests/test_httpclient2.rb +5 -0
  47. data/tests/test_idle_connection.rb +6 -4
  48. data/tests/test_iterator.rb +97 -0
  49. data/tests/test_line_protocol.rb +33 -0
  50. data/tests/test_pause.rb +24 -0
  51. data/tests/test_set_sock_opt.rb +1 -1
  52. data/tests/test_ssl_echo_data.rb +60 -0
  53. data/tests/test_ssl_methods.rb +15 -7
  54. data/tests/test_ssl_verify.rb +4 -4
  55. data/tests/test_stomp.rb +37 -0
  56. data/tests/test_system.rb +42 -0
  57. metadata +45 -42
  58. data/lib/rubyeventmachine.jar +0 -0
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: !binary |-
4
- MTcxNDk5YWVjZDU4NjU2NzgyMzU5ZjBiNGExYmEyN2RiMDEyMDRmYg==
5
- data.tar.gz: !binary |-
6
- NDA4OGUxMjA1NzA3ZDdmMTJlODQ2MjcyY2VkM2ViMWIxMDA3M2NhOQ==
3
+ metadata.gz: 196a510820266752167782d31cc8f8b3d3ed7097
4
+ data.tar.gz: 8a7360f9dcdbf351eeecae1a386371f1de50a879
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- YmFmMjRmN2MxZWMwNzEzY2Q1NDZlM2EwNDk2M2M5MTAxMmU0OGRkN2E5ZGVk
10
- NTk1ZGE0ZjhiNDk0MzMwODI1NWQzMjhkNjEzNGY1YWEyYjg5YTMxMjY5N2E1
11
- YjQ4Njg1ZDVlZGRmMzBkMjYzNzI5NzcwYjk2OWU5YzkzMzljYzA=
12
- data.tar.gz: !binary |-
13
- MWM1NDY3MzY3ZDA5MWVmMjk1ZWJhZmEwY2Q4OTIxMTEzZjY0YWNjYTM4ZWI4
14
- ZTI0ODBlYmEzMjI4YWQwZWQ3ZTVjMzBjMWRlOTY0YWExYTlhYTkzN2U2MWQ0
15
- M2IxMWQ1YTc2MTk0YjI4NjU0YmFkNjM3NzU0MTIwMjQ0OWMwYjE=
6
+ metadata.gz: b04803ccb631b97c9f12818d0b9529f0c79a7b0596e7c0f18a9c72e99f12c4e1683e7528b47c531d0b3d510ebf1d9f64338db99b94c8f88b4de44f5255872f44
7
+ data.tar.gz: 500b5af57cd9247c169938acef5e9c72babda5d60a6c99aadcacd06d1045146f40867846940a93d22cb1c3e7902f5073bc9d71a7b56d07fddca86aa0c3332bd0
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ script: rake compile test
2
+ language: ruby
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.3
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ - jruby
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: rbx-18mode
12
+ - rvm: rbx-19mode
data/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ ## 1.0.4
4
+ * calling pause from receive_data takes effect immediately [#464]
5
+ * reactor_running? returns false after fork [#455]
6
+ * fix infinite loop on double close [edc4d0e6, #441, #445]
7
+ * fix compilation issue on llvm [#433]
8
+ * fix socket error codes on win32 [ff811a81]
9
+ * fix EM.stop latency when timers exist [8b613d05, #426]
10
+ * fix infinite loop when system time changes [1427a2c80, #428]
11
+ * fix crash when callin attach/detach in the same tick [#427]
12
+ * fix compilation issue on solaris [#416]
13
+
14
+ ## 1.0.3 (March 8, 2013)
15
+ * EM.system was broken in 1.0.2 release [#413]
16
+
17
+ ## 1.0.2 (March 8, 2013)
18
+ * binary win32 gems now include fastfilereader shim [#222]
19
+ * fix long-standing connection timeout issues [27fdd5b, igrigorik/em-http-request#222]
20
+ * http and line protocol cleanups [#193, #151]
21
+ * reactor return value cleanup [#225]
22
+ * fix double require from gemspec [#284]
23
+ * fix smtp server reset behavior [#351]
24
+ * fix EM.system argument handling [#322]
25
+ * ruby 1.9 compat in smtp server and stomp protocols [#349, #315]
26
+ * fix pause from post_init [#380]
27
+
28
+ ## 1.0.1 (February 27, 2013)
29
+ * use rb_wait_for_single_fd() on ruby 2.0 to fix rb_thread_select() deprecation [#363]
30
+ * fix epoll/kqueue mode in ruby 2.0 by removing calls to rb_enable_interrupt() [#248, #389]
31
+ * fix memory leak when verifying ssl cerificates [#403]
32
+ * fix initial connection delay [#393, #374]
33
+ * fix build on windows [#371]
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
2
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # About EventMachine #
1
+ # About EventMachine [![Code Climate](https://codeclimate.com/github/eventmachine/eventmachine.png)](https://codeclimate.com/github/eventmachine/eventmachine)
2
2
 
3
3
 
4
4
  ## What is EventMachine ##
@@ -75,7 +75,7 @@ Here's a fully-functional echo server written with EventMachine:
75
75
 
76
76
  def unbind
77
77
  puts "-- someone disconnected from the echo server!"
78
- end
78
+ end
79
79
  end
80
80
 
81
81
  # Note that this will block current thread.
data/README_JP.md CHANGED
@@ -8,7 +8,15 @@ JRuby実装のビルドとインストール
8
8
  $ jgem build eventmachine.gemspec
9
9
 
10
10
  // jruby用のgemを作成
11
- $ jruby -S rake java gem
11
+ $ jruby rake java gem
12
12
 
13
13
  // インストール
14
- $ jgem install pkg/sonixlabs-eventmachine-java-1.0.x-java
14
+ $ jgem install sonixlabs-eventmachine-java-1.0.x-java
15
+
16
+ // rubygemsにpush
17
+ $ gem push sonixlabs-eventmachine-java-1.0.x-java
18
+
19
+
20
+ # fork
21
+
22
+ * jruby_tls: https://github.com/asynchrony/eventmachine/tree/jruby_tls
data/eventmachine.gemspec CHANGED
@@ -1,22 +1,25 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/em/version', __FILE__)
2
+ $:.unshift File.expand_path("../lib", __FILE__)
3
+ require "em/version"
4
+
3
5
 
4
6
  Gem::Specification.new do |s|
5
7
  s.name = 'sonixlabs-eventmachine-java'
6
8
  s.version = EventMachine::VERSION
7
- s.homepage = 'https://github.com/sonixlabs/eventmachine'
9
+ s.homepage = 'http://rubyeventmachine.com'
8
10
  s.rubyforge_project = 'eventmachine'
9
11
  s.platform = 'java' # jruby only
12
+ s.licenses = ["Ruby", "GPL"]
10
13
 
11
- s.authors = ["Kazuhiro Yamada"]
12
- s.email = ["sonixlabs@sonix.asia", "yamadakazu45@gmail.com"]
14
+ s.authors = ["Francis Cianfrocca", "Aman Gupta"]
15
+ s.email = ["garbagecat10@gmail.com", "aman@tmm1.net"]
13
16
 
14
17
  s.files = `git ls-files`.split("\n")
15
18
  s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
16
19
 
17
- s.add_development_dependency 'rake-compiler', '~> 0.8.1'
18
- s.add_development_dependency 'yard', ">= 0.7.2"
19
- s.add_development_dependency 'bluecloth'
20
+ s.add_development_dependency 'rake-compiler', '~> 0.8.3'
21
+ s.add_development_dependency 'yard', ">= 0.8.5.2"
22
+ s.add_development_dependency 'bluecloth' unless RUBY_PLATFORM =~ /java/
20
23
 
21
24
  s.summary = 'Ruby/EventMachine library'
22
25
  s.description = "EventMachine implements a fast, single-threaded engine for arbitrary network
data/ext/binder.cpp CHANGED
@@ -32,7 +32,7 @@ STATIC Bindable_t::CreateBinding
32
32
  unsigned long Bindable_t::CreateBinding()
33
33
  {
34
34
  static unsigned long num = 0;
35
- while(BindingBag[++num]);
35
+ while(BindingBag[++num]) {}
36
36
  return num;
37
37
  }
38
38
 
data/ext/cmain.cpp CHANGED
@@ -259,6 +259,7 @@ evma_num_close_scheduled
259
259
 
260
260
  extern "C" int evma_num_close_scheduled ()
261
261
  {
262
+ ensure_eventmachine("evma_num_close_scheduled");
262
263
  return EventMachine->NumCloseScheduled;
263
264
  }
264
265
 
@@ -282,6 +283,16 @@ extern "C" const unsigned long evma_create_unix_domain_server (const char *filen
282
283
  return EventMachine->CreateUnixDomainServer (filename);
283
284
  }
284
285
 
286
+ /***********************
287
+ evma_attach_sd
288
+ ************************/
289
+
290
+ extern "C" const unsigned long evma_attach_sd (int sd)
291
+ {
292
+ ensure_eventmachine("evma_attach_sd");
293
+ return EventMachine->AttachSD (sd);
294
+ }
295
+
285
296
  /*************************
286
297
  evma_open_datagram_socket
287
298
  *************************/
data/ext/ed.cpp CHANGED
@@ -217,6 +217,8 @@ EventableDescriptor::ScheduleClose
217
217
 
218
218
  void EventableDescriptor::ScheduleClose (bool after_writing)
219
219
  {
220
+ if (IsCloseScheduled())
221
+ return;
220
222
  MyEventMachine->NumCloseScheduled++;
221
223
  // KEEP THIS SYNCHRONIZED WITH ::IsCloseScheduled.
222
224
  if (after_writing)
@@ -460,6 +462,7 @@ ConnectionDescriptor::SetConnectPending
460
462
  void ConnectionDescriptor::SetConnectPending(bool f)
461
463
  {
462
464
  bConnectPending = f;
465
+ MyEventMachine->QueueHeartbeat(this);
463
466
  _UpdateEvents();
464
467
  }
465
468
 
@@ -764,7 +767,11 @@ void ConnectionDescriptor::Read()
764
767
 
765
768
 
766
769
  int r = read (sd, readbuffer, sizeof(readbuffer) - 1);
770
+ #ifdef OS_WIN32
771
+ int e = WSAGetLastError();
772
+ #else
767
773
  int e = errno;
774
+ #endif
768
775
  //cerr << "<R:" << r << ">";
769
776
 
770
777
  if (r > 0) {
@@ -778,6 +785,8 @@ void ConnectionDescriptor::Read()
778
785
  // a security guard against buffer overflows.
779
786
  readbuffer [r] = 0;
780
787
  _DispatchInboundData (readbuffer, r);
788
+ if (bPaused)
789
+ break;
781
790
  }
782
791
  else if (r == 0) {
783
792
  break;
@@ -980,11 +989,7 @@ void ConnectionDescriptor::_WriteOutboundData()
980
989
  // Max of 16 outbound pages at a time
981
990
  if (iovcnt > 16) iovcnt = 16;
982
991
 
983
- #ifdef CC_SUNWspro
984
- struct iovec iov[16];
985
- #else
986
- struct iovec iov[ iovcnt ];
987
- #endif
992
+ iovec iov[16];
988
993
 
989
994
  for(int i = 0; i < iovcnt; i++){
990
995
  OutboundPage *op = &(OutboundPages[i]);
@@ -1031,7 +1036,11 @@ void ConnectionDescriptor::_WriteOutboundData()
1031
1036
  #endif
1032
1037
 
1033
1038
  bool err = false;
1039
+ #ifdef OS_WIN32
1040
+ int e = WSAGetLastError();
1041
+ #else
1034
1042
  int e = errno;
1043
+ #endif
1035
1044
  if (bytes_written < 0) {
1036
1045
  err = true;
1037
1046
  bytes_written = 0;
@@ -1445,14 +1454,16 @@ void AcceptorDescriptor::Read()
1445
1454
  (*EventCallback) (GetBinding(), EM_CONNECTION_ACCEPTED, NULL, cd->GetBinding());
1446
1455
  }
1447
1456
  #ifdef HAVE_EPOLL
1448
- cd->GetEpollEvent()->events = EPOLLIN | (cd->SelectForWrite() ? EPOLLOUT : 0);
1457
+ cd->GetEpollEvent()->events =
1458
+ (cd->SelectForRead() ? EPOLLIN : 0) | (cd->SelectForWrite() ? EPOLLOUT : 0);
1449
1459
  #endif
1450
1460
  assert (MyEventMachine);
1451
1461
  MyEventMachine->Add (cd);
1452
1462
  #ifdef HAVE_KQUEUE
1453
1463
  if (cd->SelectForWrite())
1454
1464
  MyEventMachine->ArmKqueueWriter (cd);
1455
- MyEventMachine->ArmKqueueReader (cd);
1465
+ if (cd->SelectForRead())
1466
+ MyEventMachine->ArmKqueueReader (cd);
1456
1467
  #endif
1457
1468
  }
1458
1469
 
@@ -1660,7 +1671,11 @@ void DatagramDescriptor::Write()
1660
1671
 
1661
1672
  // The nasty cast to (char*) is needed because Windows is brain-dead.
1662
1673
  int s = sendto (sd, (char*)op->Buffer, op->Length, 0, (struct sockaddr*)&(op->From), sizeof(op->From));
1674
+ #ifdef OS_WIN32
1675
+ int e = WSAGetLastError();
1676
+ #else
1663
1677
  int e = errno;
1678
+ #endif
1664
1679
 
1665
1680
  OutboundDataSize -= op->Length;
1666
1681
  op->Free();
data/ext/ed.h CHANGED
@@ -69,14 +69,14 @@ class EventableDescriptor: public Bindable_t
69
69
  virtual bool GetSubprocessPid (pid_t*) {return false;}
70
70
 
71
71
  virtual void StartTls() {}
72
- virtual void SetTlsParms (const char *privkey_filename, const char *certchain_filename, bool verify_peer) {}
72
+ virtual void SetTlsParms (const char *, const char *, bool) {}
73
73
 
74
74
  #ifdef WITH_SSL
75
75
  virtual X509 *GetPeerCert() {return NULL;}
76
76
  #endif
77
77
 
78
78
  virtual uint64_t GetCommInactivityTimeout() {return 0;}
79
- virtual int SetCommInactivityTimeout (uint64_t value) {return 0;}
79
+ virtual int SetCommInactivityTimeout (uint64_t) {return 0;}
80
80
  uint64_t GetPendingConnectTimeout();
81
81
  int SetPendingConnectTimeout (uint64_t value);
82
82
  uint64_t GetLastActivity() { return LastActivity; }
@@ -215,7 +215,7 @@ class ConnectionDescriptor: public EventableDescriptor
215
215
  protected:
216
216
  struct OutboundPage {
217
217
  OutboundPage (const char *b, int l, int o=0): Buffer(b), Length(l), Offset(o) {}
218
- void Free() {if (Buffer) free ((char*)Buffer); }
218
+ void Free() {if (Buffer) free (const_cast<char*>(Buffer)); }
219
219
  const char *Buffer;
220
220
  int Length;
221
221
  int Offset;
@@ -292,7 +292,7 @@ class DatagramDescriptor: public EventableDescriptor
292
292
  protected:
293
293
  struct OutboundPage {
294
294
  OutboundPage (const char *b, int l, struct sockaddr_in f, int o=0): Buffer(b), Length(l), Offset(o), From(f) {}
295
- void Free() {if (Buffer) free ((char*)Buffer); }
295
+ void Free() {if (Buffer) free (const_cast<char*>(Buffer)); }
296
296
  const char *Buffer;
297
297
  int Length;
298
298
  int Offset;
@@ -354,7 +354,7 @@ class PipeDescriptor: public EventableDescriptor
354
354
  protected:
355
355
  struct OutboundPage {
356
356
  OutboundPage (const char *b, int l, int o=0): Buffer(b), Length(l), Offset(o) {}
357
- void Free() {if (Buffer) free ((char*)Buffer); }
357
+ void Free() {if (Buffer) free (const_cast<char*>(Buffer)); }
358
358
  const char *Buffer;
359
359
  int Length;
360
360
  int Offset;
data/ext/em.cpp CHANGED
@@ -382,15 +382,27 @@ EventMachine_t::_DispatchHeartbeats
382
382
 
383
383
  void EventMachine_t::_DispatchHeartbeats()
384
384
  {
385
+ // Store the first processed heartbeat descriptor and bail out if
386
+ // we see it again. This fixes an infinite loop in case the system time
387
+ // is changed out from underneath MyCurrentLoopTime.
388
+ const EventableDescriptor *head = NULL;
389
+
385
390
  while (true) {
386
391
  multimap<uint64_t,EventableDescriptor*>::iterator i = Heartbeats.begin();
387
392
  if (i == Heartbeats.end())
388
393
  break;
389
394
  if (i->first > MyCurrentLoopTime)
390
395
  break;
396
+
391
397
  EventableDescriptor *ed = i->second;
398
+ if (ed == head)
399
+ break;
400
+
392
401
  ed->Heartbeat();
393
402
  QueueHeartbeat(ed);
403
+
404
+ if (head == NULL)
405
+ head = ed;
394
406
  }
395
407
  }
396
408
 
@@ -482,8 +494,7 @@ void EventMachine_t::Run()
482
494
  _AddNewDescriptors();
483
495
  _ModifyDescriptors();
484
496
 
485
- if (!_RunOnce())
486
- break;
497
+ _RunOnce();
487
498
  if (bTerminateSignalReceived)
488
499
  break;
489
500
  }
@@ -494,27 +505,24 @@ void EventMachine_t::Run()
494
505
  EventMachine_t::_RunOnce
495
506
  ************************/
496
507
 
497
- bool EventMachine_t::_RunOnce()
508
+ void EventMachine_t::_RunOnce()
498
509
  {
499
- bool ret;
500
510
  if (bEpoll)
501
- ret = _RunEpollOnce();
511
+ _RunEpollOnce();
502
512
  else if (bKqueue)
503
- ret = _RunKqueueOnce();
513
+ _RunKqueueOnce();
504
514
  else
505
- ret = _RunSelectOnce();
515
+ _RunSelectOnce();
506
516
  _DispatchHeartbeats();
507
517
  _CleanupSockets();
508
- return ret;
509
518
  }
510
519
 
511
520
 
512
-
513
521
  /*****************************
514
522
  EventMachine_t::_RunEpollOnce
515
523
  *****************************/
516
524
 
517
- bool EventMachine_t::_RunEpollOnce()
525
+ void EventMachine_t::_RunEpollOnce()
518
526
  {
519
527
  #ifdef HAVE_EPOLL
520
528
  assert (epfd != -1);
@@ -524,17 +532,22 @@ bool EventMachine_t::_RunEpollOnce()
524
532
 
525
533
  #ifdef BUILD_FOR_RUBY
526
534
  int ret = 0;
535
+
536
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
537
+ if ((ret = rb_wait_for_single_fd(epfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
538
+ #else
527
539
  fd_set fdreads;
528
540
 
529
541
  FD_ZERO(&fdreads);
530
542
  FD_SET(epfd, &fdreads);
531
543
 
532
544
  if ((ret = rb_thread_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
545
+ #endif
533
546
  if (ret == -1) {
534
547
  assert(errno != EINVAL);
535
548
  assert(errno != EBADF);
536
549
  }
537
- return true;
550
+ return;
538
551
  }
539
552
 
540
553
  TRAP_BEG;
@@ -572,8 +585,6 @@ bool EventMachine_t::_RunEpollOnce()
572
585
  timeval tv = {0, ((errno == EINTR) ? 5 : 50) * 1000};
573
586
  EmSelect (0, NULL, NULL, NULL, &tv);
574
587
  }
575
-
576
- return true;
577
588
  #else
578
589
  throw std::runtime_error ("epoll is not implemented on this platform");
579
590
  #endif
@@ -584,7 +595,7 @@ bool EventMachine_t::_RunEpollOnce()
584
595
  EventMachine_t::_RunKqueueOnce
585
596
  ******************************/
586
597
 
587
- bool EventMachine_t::_RunKqueueOnce()
598
+ void EventMachine_t::_RunKqueueOnce()
588
599
  {
589
600
  #ifdef HAVE_KQUEUE
590
601
  assert (kqfd != -1);
@@ -598,17 +609,22 @@ bool EventMachine_t::_RunKqueueOnce()
598
609
 
599
610
  #ifdef BUILD_FOR_RUBY
600
611
  int ret = 0;
612
+
613
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
614
+ if ((ret = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
615
+ #else
601
616
  fd_set fdreads;
602
617
 
603
618
  FD_ZERO(&fdreads);
604
619
  FD_SET(kqfd, &fdreads);
605
620
 
606
621
  if ((ret = rb_thread_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
622
+ #endif
607
623
  if (ret == -1) {
608
624
  assert(errno != EINVAL);
609
625
  assert(errno != EBADF);
610
626
  }
611
- return true;
627
+ return;
612
628
  }
613
629
 
614
630
  TRAP_BEG;
@@ -659,8 +675,6 @@ bool EventMachine_t::_RunKqueueOnce()
659
675
  rb_thread_schedule();
660
676
  }
661
677
  #endif
662
-
663
- return true;
664
678
  #else
665
679
  throw std::runtime_error ("kqueue is not implemented on this platform");
666
680
  #endif
@@ -673,7 +687,7 @@ EventMachine_t::_TimeTilNextEvent
673
687
 
674
688
  timeval EventMachine_t::_TimeTilNextEvent()
675
689
  {
676
- // 29jul11: Changed calculation base from MyCurrentLoopTime to the
690
+ // 29jul11: Changed calculation base from MyCurrentLoopTime to the
677
691
  // real time. As MyCurrentLoopTime is set at the beginning of an
678
692
  // iteration and this calculation is done at the end, evenmachine
679
693
  // will potentially oversleep by the amount of time the iteration
@@ -695,10 +709,12 @@ timeval EventMachine_t::_TimeTilNextEvent()
695
709
  if (!NewDescriptors.empty() || !ModifiedDescriptors.empty()) {
696
710
  next_event = current_time;
697
711
  }
698
-
712
+
699
713
  timeval tv;
700
714
 
701
- if (next_event == 0 || NumCloseScheduled > 0) {
715
+ if (NumCloseScheduled > 0 || bTerminateSignalReceived) {
716
+ tv.tv_sec = tv.tv_usec = 0;
717
+ } else if (next_event == 0) {
702
718
  tv = Quantum;
703
719
  } else {
704
720
  if (next_event > current_time) {
@@ -833,37 +849,17 @@ int SelectData_t::_Select()
833
849
  EventMachine_t::_RunSelectOnce
834
850
  ******************************/
835
851
 
836
- bool EventMachine_t::_RunSelectOnce()
852
+ void EventMachine_t::_RunSelectOnce()
837
853
  {
838
854
  // Crank the event machine once.
839
855
  // If there are no descriptors to process, then sleep
840
856
  // for a few hundred mills to avoid busy-looping.
841
- // Return T/F to indicate whether we should continue.
842
857
  // This is based on a select loop. Alternately provide epoll
843
858
  // if we know we're running on a 2.6 kernel.
844
859
  // epoll will be effective if we provide it as an alternative,
845
860
  // however it has the same problem interoperating with Ruby
846
861
  // threads that select does.
847
862
 
848
- //cerr << "X";
849
-
850
- /* This protection is now obsolete, because we will ALWAYS
851
- * have at least one descriptor (the loop-breaker) to read.
852
- */
853
- /*
854
- if (Descriptors.size() == 0) {
855
- #ifdef OS_UNIX
856
- timeval tv = {0, 200 * 1000};
857
- EmSelect (0, NULL, NULL, NULL, &tv);
858
- return true;
859
- #endif
860
- #ifdef OS_WIN32
861
- Sleep (200);
862
- return true;
863
- #endif
864
- }
865
- */
866
-
867
863
  SelectData_t SelectData;
868
864
  /*
869
865
  fd_set fdreads, fdwrites;
@@ -965,8 +961,6 @@ bool EventMachine_t::_RunSelectOnce()
965
961
  }
966
962
  }
967
963
  }
968
-
969
- return true;
970
964
  }
971
965
 
972
966
  void EventMachine_t::_CleanBadDescriptors()
@@ -1419,6 +1413,14 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1419
1413
  // Prevent the descriptor from being modified, in case DetachFD was called from a timer or next_tick
1420
1414
  ModifiedDescriptors.erase (ed);
1421
1415
 
1416
+ // Prevent the descriptor from being added, in case DetachFD was called in the same tick as AttachFD
1417
+ for (size_t i = 0; i < NewDescriptors.size(); i++) {
1418
+ if (ed == NewDescriptors[i]) {
1419
+ NewDescriptors.erase(NewDescriptors.begin() + i);
1420
+ break;
1421
+ }
1422
+ }
1423
+
1422
1424
  // Set MySocket = INVALID_SOCKET so ShouldDelete() is true (and the descriptor gets deleted and removed),
1423
1425
  // and also to prevent anyone from calling close() on the detached fd
1424
1426
  ed->SetSocketInvalid();
@@ -1511,8 +1513,6 @@ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int por
1511
1513
  if (!bind_here)
1512
1514
  return 0;
1513
1515
 
1514
- unsigned long output_binding = 0;
1515
-
1516
1516
  //struct sockaddr_in sin;
1517
1517
 
1518
1518
  int sd_accept = socket (family, SOCK_STREAM, 0);
@@ -1549,25 +1549,7 @@ const unsigned long EventMachine_t::CreateTcpServer (const char *server, int por
1549
1549
  goto fail;
1550
1550
  }
1551
1551
 
1552
- {
1553
- // Set the acceptor non-blocking.
1554
- // THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.
1555
- if (!SetSocketNonblocking (sd_accept)) {
1556
- //int val = fcntl (sd_accept, F_GETFL, 0);
1557
- //if (fcntl (sd_accept, F_SETFL, val | O_NONBLOCK) == -1) {
1558
- goto fail;
1559
- }
1560
- }
1561
-
1562
- { // Looking good.
1563
- AcceptorDescriptor *ad = new AcceptorDescriptor (sd_accept, this);
1564
- if (!ad)
1565
- throw std::runtime_error ("unable to allocate acceptor");
1566
- Add (ad);
1567
- output_binding = ad->GetBinding();
1568
- }
1569
-
1570
- return output_binding;
1552
+ return AttachSD(sd_accept);
1571
1553
 
1572
1554
  fail:
1573
1555
  if (sd_accept != INVALID_SOCKET)
@@ -1858,7 +1840,6 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
1858
1840
 
1859
1841
  // The whole rest of this function is only compiled on Unix systems.
1860
1842
  #ifdef OS_UNIX
1861
- unsigned long output_binding = 0;
1862
1843
 
1863
1844
  struct sockaddr_un s_sun;
1864
1845
 
@@ -1896,6 +1877,24 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
1896
1877
  goto fail;
1897
1878
  }
1898
1879
 
1880
+ return AttachSD(sd_accept);
1881
+
1882
+ fail:
1883
+ if (sd_accept != INVALID_SOCKET)
1884
+ close (sd_accept);
1885
+ return 0;
1886
+ #endif // OS_UNIX
1887
+ }
1888
+
1889
+
1890
+ /**************************************
1891
+ EventMachine_t::AttachSD
1892
+ **************************************/
1893
+
1894
+ const unsigned long EventMachine_t::AttachSD (int sd_accept)
1895
+ {
1896
+ unsigned long output_binding = 0;
1897
+
1899
1898
  {
1900
1899
  // Set the acceptor non-blocking.
1901
1900
  // THIS IS CRUCIALLY IMPORTANT because we read it in a select loop.
@@ -1920,7 +1919,6 @@ const unsigned long EventMachine_t::CreateUnixDomainServer (const char *filename
1920
1919
  if (sd_accept != INVALID_SOCKET)
1921
1920
  close (sd_accept);
1922
1921
  return 0;
1923
- #endif // OS_UNIX
1924
1922
  }
1925
1923
 
1926
1924
 
data/ext/em.h CHANGED
@@ -24,9 +24,13 @@ See the file COPYING for complete licensing information.
24
24
  #include <ruby.h>
25
25
  #define EmSelect rb_thread_select
26
26
 
27
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
28
+ #include <ruby/io.h>
29
+ #endif
30
+
27
31
  #if defined(HAVE_RBTRAP)
28
32
  #include <rubysig.h>
29
- #elif defined(HAVE_RB_THREAD_CHECK_INTS)
33
+ #elif defined(HAVE_RB_ENABLE_INTERRUPT)
30
34
  extern "C" {
31
35
  void rb_enable_interrupt(void);
32
36
  void rb_disable_interrupt(void);
@@ -84,6 +88,7 @@ class EventMachine_t
84
88
  const unsigned long CreateTcpServer (const char *, int);
85
89
  const unsigned long OpenDatagramSocket (const char *, int);
86
90
  const unsigned long CreateUnixDomainServer (const char*);
91
+ const unsigned long AttachSD (int);
87
92
  const unsigned long OpenKeyboard();
88
93
  //const char *Popen (const char*, const char*);
89
94
  const unsigned long Socketpair (char* const*);
@@ -141,7 +146,7 @@ class EventMachine_t
141
146
  uint64_t GetRealTime();
142
147
 
143
148
  private:
144
- bool _RunOnce();
149
+ void _RunOnce();
145
150
  void _RunTimers();
146
151
  void _UpdateTime();
147
152
  void _AddNewDescriptors();
@@ -149,9 +154,9 @@ class EventMachine_t
149
154
  void _InitializeLoopBreaker();
150
155
  void _CleanupSockets();
151
156
 
152
- bool _RunSelectOnce();
153
- bool _RunEpollOnce();
154
- bool _RunKqueueOnce();
157
+ void _RunSelectOnce();
158
+ void _RunEpollOnce();
159
+ void _RunKqueueOnce();
155
160
 
156
161
  void _ModifyEpollEvent (EventableDescriptor*);
157
162
  void _DispatchHeartbeats();
data/ext/eventmachine.h CHANGED
@@ -64,6 +64,7 @@ extern "C" {
64
64
  void evma_stop_tcp_server (const unsigned long signature);
65
65
  const unsigned long evma_create_tcp_server (const char *address, int port);
66
66
  const unsigned long evma_create_unix_domain_server (const char *filename);
67
+ const unsigned long evma_attach_sd (int sd);
67
68
  const unsigned long evma_open_datagram_socket (const char *server, int port);
68
69
  const unsigned long evma_open_keyboard();
69
70
  void evma_set_tls_parms (const unsigned long binding, const char *privatekey_filename, const char *certchain_filenane, int verify_peer);