sonixlabs-eventmachine-java 1.0.0.rc.7-java → 1.0.3.1-java

Sign up to get free protection for your applications and to get access to all the features.
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);