[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#829650: jessie-pu: package ruby-eventmachine/1.0.3-6+deb8u1



Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

Dear Release Team,

The Security Team suggested fixing the TEMP-0678512-2E167C [1] security
issue through a point release.

The issue is a remotely triggerable crash due to stack overflow.

Please see the debdiff attached.

The fix for Wheezy which is very similar was discussed [2] on the Wheezy
LTS list.

Cheers,
Balint

[1] https://security-tracker.debian.org/tracker/TEMP-0678512-2E167C
[2] https://lists.debian.org/debian-lts/2016/06/msg00141.html
diff -Nru ruby-eventmachine-1.0.3/debian/changelog ruby-eventmachine-1.0.3/debian/changelog
--- ruby-eventmachine-1.0.3/debian/changelog	2014-04-07 00:34:46.000000000 +0200
+++ ruby-eventmachine-1.0.3/debian/changelog	2016-07-04 22:00:03.000000000 +0200
@@ -1,3 +1,12 @@
+ruby-eventmachine (1.0.3-6+deb8u1) stable; urgency=medium
+
+  * Team upload
+  * Fix remotely triggerable crash due to FD handling
+    (Closes: #678512, #696015)
+  * Fix memory leak caused when fixing crash
+
+ -- Balint Reczey <balint@balintreczey.hu>  Mon, 04 Jul 2016 21:48:06 +0200
+
 ruby-eventmachine (1.0.3-6) unstable; urgency=low
 
   * Bump gem2deb build dependency to 0.7.5~
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch ruby-eventmachine-1.0.3/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch
--- ruby-eventmachine-1.0.3/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,217 @@
+From eab3baaba75c8c9e549aea54d3b356ab287a57b0 Mon Sep 17 00:00:00 2001
+From: Patrick Reynolds <patrick.reynolds@github.com>
+Date: Tue, 11 Mar 2014 16:01:25 -0500
+Subject: [PATCH 1/3] use ruby select api with expandable fd sets
+
+Conflicts:
+	ext/em.h
+---
+ ext/em.cpp             | 54 +++++++++++++++++++++++++-------------------------
+ ext/em.h               | 10 +++++-----
+ tests/test_many_fds.rb | 22 ++++++++++++++++++++
+ 3 files changed, 54 insertions(+), 32 deletions(-)
+ create mode 100644 tests/test_many_fds.rb
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index 670da31..6a3a2ef 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -524,12 +524,12 @@ void EventMachine_t::_RunEpollOnce()
+ 	#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ 	if ((ret = rb_wait_for_single_fd(epfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
+ 	#else
+-	fd_set fdreads;
++	rb_fdset_t fdreads;
+ 
+-	FD_ZERO(&fdreads);
+-	FD_SET(epfd, &fdreads);
++	rb_fd_init(&fdreads);
++	rb_fd_set(epfd, &fdreads);
+ 
+-	if ((ret = rb_thread_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
++	if ((ret = rb_thread_fd_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ 	#endif
+ 		if (ret == -1) {
+ 			assert(errno != EINVAL);
+@@ -601,12 +601,12 @@ void EventMachine_t::_RunKqueueOnce()
+ 	#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ 	if ((ret = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
+ 	#else
+-	fd_set fdreads;
++	rb_fdset_t fdreads;
+ 
+-	FD_ZERO(&fdreads);
+-	FD_SET(kqfd, &fdreads);
++	rb_fd_init(&fdreads);
++	rb_fd_set(kqfd, &fdreads);
+ 
+-	if ((ret = rb_thread_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
++	if ((ret = rb_thread_fd_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ 	#endif
+ 		if (ret == -1) {
+ 			assert(errno != EINVAL);
+@@ -792,9 +792,9 @@ SelectData_t::SelectData_t
+ SelectData_t::SelectData_t()
+ {
+ 	maxsocket = 0;
+-	FD_ZERO (&fdreads);
+-	FD_ZERO (&fdwrites);
+-	FD_ZERO (&fderrors);
++	rb_fd_init (&fdreads);
++	rb_fd_init (&fdwrites);
++	rb_fd_init (&fderrors);
+ }
+ 
+ 
+@@ -807,7 +807,7 @@ _SelectDataSelect
+ static VALUE _SelectDataSelect (void *v)
+ {
+ 	SelectData_t *sd = (SelectData_t*)v;
+-	sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
++	sd->nSockets = rb_fd_select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
+ 	return Qnil;
+ }
+ #endif
+@@ -848,9 +848,9 @@ void EventMachine_t::_RunSelectOnce()
+ 
+ 	SelectData_t SelectData;
+ 	/*
+-	fd_set fdreads, fdwrites;
+-	FD_ZERO (&fdreads);
+-	FD_ZERO (&fdwrites);
++	rb_fdset_t fdreads, fdwrites;
++	rb_fd_init (&fdreads);
++	rb_fd_init (&fdwrites);
+ 
+ 	int maxsocket = 0;
+ 	*/
+@@ -860,7 +860,7 @@ void EventMachine_t::_RunSelectOnce()
+ 	// running on localhost with a randomly-chosen port. (*Puke*)
+ 	// Windows has a version of the Unix pipe() library function, but it doesn't
+ 	// give you back descriptors that are selectable.
+-	FD_SET (LoopBreakerReader, &(SelectData.fdreads));
++	rb_fd_set (LoopBreakerReader, &(SelectData.fdreads));
+ 	if (SelectData.maxsocket < LoopBreakerReader)
+ 		SelectData.maxsocket = LoopBreakerReader;
+ 
+@@ -875,15 +875,15 @@ void EventMachine_t::_RunSelectOnce()
+ 		assert (sd != INVALID_SOCKET);
+ 
+ 		if (ed->SelectForRead())
+-			FD_SET (sd, &(SelectData.fdreads));
++			rb_fd_set (sd, &(SelectData.fdreads));
+ 		if (ed->SelectForWrite())
+-			FD_SET (sd, &(SelectData.fdwrites));
++			rb_fd_set (sd, &(SelectData.fdwrites));
+ 
+ 		#ifdef OS_WIN32
+ 		/* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
+ 		   Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
+ 		*/
+-		FD_SET (sd, &(SelectData.fderrors));
++		rb_fd_set (sd, &(SelectData.fderrors));
+ 		#endif
+ 
+ 		if (SelectData.maxsocket < sd)
+@@ -918,15 +918,15 @@ void EventMachine_t::_RunSelectOnce()
+ 					continue;
+ 				assert (sd != INVALID_SOCKET);
+ 
+-				if (FD_ISSET (sd, &(SelectData.fdwrites)))
++				if (rb_fd_isset (sd, &(SelectData.fdwrites)))
+ 					ed->Write();
+-				if (FD_ISSET (sd, &(SelectData.fdreads)))
++				if (rb_fd_isset (sd, &(SelectData.fdreads)))
+ 					ed->Read();
+-				if (FD_ISSET (sd, &(SelectData.fderrors)))
++				if (rb_fd_isset (sd, &(SelectData.fderrors)))
+ 					ed->HandleError();
+ 			}
+ 
+-			if (FD_ISSET (LoopBreakerReader, &(SelectData.fdreads)))
++			if (rb_fd_isset (LoopBreakerReader, &(SelectData.fdreads)))
+ 				_ReadLoopBreaker();
+ 		}
+ 		else if (s < 0) {
+@@ -964,11 +964,11 @@ void EventMachine_t::_CleanBadDescriptors()
+ 		tv.tv_sec = 0;
+ 		tv.tv_usec = 0;
+ 
+-		fd_set fds;
+-		FD_ZERO(&fds);
+-		FD_SET(sd, &fds);
++		rb_fdset_t fds;
++		rb_fd_init(&fds);
++		rb_fd_set(sd, &fds);
+ 
+-		int ret = select(sd + 1, &fds, NULL, NULL, &tv);
++		int ret = rb_fd_select(sd + 1, &fds, NULL, NULL, &tv);
+ 
+ 		if (ret == -1) {
+ 			if (errno == EBADF)
+diff --git a/ext/em.h b/ext/em.h
+index df68ec1..ff7c26c 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -22,7 +22,7 @@ See the file COPYING for complete licensing information.
+ 
+ #ifdef BUILD_FOR_RUBY
+   #include <ruby.h>
+-  #define EmSelect rb_thread_select
++  #define EmSelect rb_thread_fd_select
+ 
+   #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+     #include <ruby/io.h>
+@@ -57,7 +57,7 @@ See the file COPYING for complete licensing information.
+     #define RSTRING_LENINT(str) RSTRING_LEN(str)
+   #endif
+ #else
+-  #define EmSelect select
++  #define EmSelect rb_fd_select
+ #endif
+ 
+ class EventableDescriptor;
+@@ -233,9 +233,9 @@ struct SelectData_t
+ 	int _Select();
+ 
+ 	int maxsocket;
+-	fd_set fdreads;
+-	fd_set fdwrites;
+-	fd_set fderrors;
++	rb_fdset_t fdreads;
++	rb_fdset_t fdwrites;
++	rb_fdset_t fderrors;
+ 	timeval tv;
+ 	int nSockets;
+ };
+diff --git a/tests/test_many_fds.rb b/tests/test_many_fds.rb
+new file mode 100644
+index 0000000..74dc926
+--- /dev/null
++++ b/tests/test_many_fds.rb
+@@ -0,0 +1,22 @@
++require 'em_test_helper'
++require 'socket'
++
++class TestManyFDs < Test::Unit::TestCase
++  def setup
++    @port = next_port
++  end
++
++  def test_connection_class_cache
++    mod = Module.new
++    a = nil
++    Process.setrlimit(Process::RLIMIT_NOFILE,4096);
++    EM.run {
++      EM.start_server '127.0.0.1', @port, mod
++      1100.times do
++        a = EM.connect '127.0.0.1', @port, mod
++        assert_kind_of EM::Connection, a
++      end
++      EM.stop
++    }
++  end
++end
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch ruby-eventmachine-1.0.3/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch
--- ruby-eventmachine-1.0.3/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,44 @@
+From ef5dac813ef3d10423ec7ca8255eea6d873278f1 Mon Sep 17 00:00:00 2001
+From: Patrick Reynolds <patrick.reynolds@github.com>
+Date: Wed, 12 Mar 2014 00:15:41 -0500
+Subject: [PATCH 2/3] add stubs with warnings for 1.8.7 and 1.9.0
+
+---
+ ext/em.h | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/ext/em.h b/ext/em.h
+index ff7c26c..5b9279d 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -60,6 +60,27 @@ See the file COPYING for complete licensing information.
+   #define EmSelect rb_fd_select
+ #endif
+ 
++#ifndef rb_fd_max
++#define fd_check(n) (((n) < FD_SETSIZE) ? 1 : 0*fprintf(stderr, "fd %d too large for select\n", (n)))
++typedef fd_set rb_fdset_t;
++#define rb_fd_zero(f) FD_ZERO(f)
++#define rb_fd_set(n, f) do { if (fd_check(n)) FD_SET((n), (f)); } while(0)
++#define rb_fd_clr(n, f) do { if (fd_check(n)) FD_CLR((n), (f)); } while(0)
++#define rb_fd_isset(n, f) (fd_check(n) ? FD_ISSET((n), (f)) : 0)
++#define rb_fd_copy(d, s, n) (*(d) = *(s))
++#define rb_fd_dup(d, s) (*(d) = *(s))
++#define rb_fd_resize(n, f)  ((void)(f))
++#define rb_fd_ptr(f)  (f)
++#define rb_fd_init(f) FD_ZERO(f)
++#define rb_fd_init_copy(d, s) (*(d) = *(s))
++#define rb_fd_term(f) ((void)(f))
++#define rb_fd_max(f)  FD_SETSIZE
++#define rb_fd_select(n, rfds, wfds, efds, timeout)  \
++  select(fd_check((n)-1) ? (n) : FD_SETSIZE, (rfds), (wfds), (efds), (timeout))
++#define rb_thread_fd_select(n, rfds, wfds, efds, timeout)  \
++  rb_thread_select(fd_check((n)-1) ? (n) : FD_SETSIZE, (rfds), (wfds), (efds), (timeout))
++#endif
++
+ class EventableDescriptor;
+ class InotifyDescriptor;
+ 
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch ruby-eventmachine-1.0.3/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch
--- ruby-eventmachine-1.0.3/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,26 @@
+From 81b673a5a0cd7f96ad7c7bbc6052bbed30b0a2a5 Mon Sep 17 00:00:00 2001
+From: Patrick Reynolds <patrick.reynolds@github.com>
+Date: Wed, 21 Jan 2015 22:34:43 -0600
+Subject: [PATCH 3/3] add comment about where the macros came from
+
+---
+ ext/em.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/ext/em.h b/ext/em.h
+index 5b9279d..05d4310 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -62,6 +62,9 @@ See the file COPYING for complete licensing information.
+ 
+ #ifndef rb_fd_max
+ #define fd_check(n) (((n) < FD_SETSIZE) ? 1 : 0*fprintf(stderr, "fd %d too large for select\n", (n)))
++// These definitions are cribbed from include/ruby/intern.h in Ruby 1.9.3,
++// with this change: any macros that read or write the nth element of an
++// fdset first call fd_check to make sure n is in bounds.
+ typedef fd_set rb_fdset_t;
+ #define rb_fd_zero(f) FD_ZERO(f)
+ #define rb_fd_set(n, f) do { if (fd_check(n)) FD_SET((n), (f)); } while(0)
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0004-must-call-raw-select-from-thread_blocking_region.patch ruby-eventmachine-1.0.3/debian/patches/0004-must-call-raw-select-from-thread_blocking_region.patch
--- ruby-eventmachine-1.0.3/debian/patches/0004-must-call-raw-select-from-thread_blocking_region.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0004-must-call-raw-select-from-thread_blocking_region.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,25 @@
+From 2fac7f4df1be8f04e4ef0d8f6887686dff66833a Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 22:29:00 -0800
+Subject: [PATCH 04/11] must call raw select() from thread_blocking_region
+
+---
+ ext/em.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index 6a3a2ef..a279893 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -807,7 +807,7 @@ _SelectDataSelect
+ static VALUE _SelectDataSelect (void *v)
+ {
+ 	SelectData_t *sd = (SelectData_t*)v;
+-	sd->nSockets = rb_fd_select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
++	sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
+ 	return Qnil;
+ }
+ #endif
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0005-epoll-kqueue-on-older-rubies-without-rb_wait_for_sin.patch ruby-eventmachine-1.0.3/debian/patches/0005-epoll-kqueue-on-older-rubies-without-rb_wait_for_sin.patch
--- ruby-eventmachine-1.0.3/debian/patches/0005-epoll-kqueue-on-older-rubies-without-rb_wait_for_sin.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0005-epoll-kqueue-on-older-rubies-without-rb_wait_for_sin.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,66 @@
+From ee8b84b9c183edadb6d7daad61a1d7ce80a0abc2 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 22:31:25 -0800
+Subject: [PATCH 05/11] epoll/kqueue on older rubies (without
+ rb_wait_for_single_fd) should use rb_thread_select with regular fdset
+
+epoll/kqueue fds are created early during ruby boot, so it is highly
+unlikely that they will ever overflow FD_SETSIZE
+---
+ ext/em.cpp | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index a279893..392bc9d 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -524,12 +524,12 @@ void EventMachine_t::_RunEpollOnce()
+ 	#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ 	if ((ret = rb_wait_for_single_fd(epfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
+ 	#else
+-	rb_fdset_t fdreads;
++	fd_set fdreads;
+ 
+-	rb_fd_init(&fdreads);
+-	rb_fd_set(epfd, &fdreads);
++	FD_ZERO(&fdreads);
++	FD_SET(epfd, &fdreads);
+ 
+-	if ((ret = rb_thread_fd_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
++	if ((ret = rb_thread_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ 	#endif
+ 		if (ret == -1) {
+ 			assert(errno != EINVAL);
+@@ -601,12 +601,12 @@ void EventMachine_t::_RunKqueueOnce()
+ 	#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ 	if ((ret = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
+ 	#else
+-	rb_fdset_t fdreads;
++	fd_set fdreads;
+ 
+-	rb_fd_init(&fdreads);
+-	rb_fd_set(kqfd, &fdreads);
++	FD_ZERO(&fdreads);
++	FD_SET(kqfd, &fdreads);
+ 
+-	if ((ret = rb_thread_fd_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
++	if ((ret = rb_thread_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ 	#endif
+ 		if (ret == -1) {
+ 			assert(errno != EINVAL);
+@@ -848,9 +848,9 @@ void EventMachine_t::_RunSelectOnce()
+ 
+ 	SelectData_t SelectData;
+ 	/*
+-	rb_fdset_t fdreads, fdwrites;
+-	rb_fd_init (&fdreads);
+-	rb_fd_init (&fdwrites);
++	fd_set fdreads, fdwrites;
++	FD_ZERO (&fdreads);
++	FD_ZERO (&fdwrites);
+ 
+ 	int maxsocket = 0;
+ 	*/
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0006-make-sure-to-clean-up-rb_fd_init-memory-during-shutd.patch ruby-eventmachine-1.0.3/debian/patches/0006-make-sure-to-clean-up-rb_fd_init-memory-during-shutd.patch
--- ruby-eventmachine-1.0.3/debian/patches/0006-make-sure-to-clean-up-rb_fd_init-memory-during-shutd.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0006-make-sure-to-clean-up-rb_fd_init-memory-during-shutd.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,42 @@
+From 18b256281c80513b8f4724261a29de4b3846249b Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 22:32:19 -0800
+Subject: [PATCH 06/11] make sure to clean up rb_fd_init memory during shutdown
+
+---
+ ext/em.cpp | 6 ++++++
+ ext/em.h   | 1 +
+ 2 files changed, 7 insertions(+)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index 392bc9d..e2a0e2b 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -797,6 +797,12 @@ SelectData_t::SelectData_t()
+ 	rb_fd_init (&fderrors);
+ }
+ 
++SelectData_t::~SelectData_t()
++{
++	rb_fd_term (&fdreads);
++	rb_fd_term (&fdwrites);
++	rb_fd_term (&fderrors);
++}
+ 
+ #ifdef BUILD_FOR_RUBY
+ /*****************
+diff --git a/ext/em.h b/ext/em.h
+index 05d4310..870623d 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -253,6 +253,7 @@ struct SelectData_t
+ struct SelectData_t
+ {
+ 	SelectData_t();
++	~SelectData_t();
+ 
+ 	int _Select();
+ 
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0007-keep-BUILD_FOR_RUBY-compat.patch ruby-eventmachine-1.0.3/debian/patches/0007-keep-BUILD_FOR_RUBY-compat.patch
--- ruby-eventmachine-1.0.3/debian/patches/0007-keep-BUILD_FOR_RUBY-compat.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0007-keep-BUILD_FOR_RUBY-compat.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,29 @@
+From 32b1a0e8499526247f2dccc35ec66768165994f6 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 22:40:10 -0800
+Subject: [PATCH 07/11] keep BUILD_FOR_RUBY compat
+
+---
+ ext/em.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ext/em.h b/ext/em.h
+index 870623d..3799bba 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -57,10 +57,10 @@ See the file COPYING for complete licensing information.
+     #define RSTRING_LENINT(str) RSTRING_LEN(str)
+   #endif
+ #else
+-  #define EmSelect rb_fd_select
++  #define EmSelect select
+ #endif
+ 
+-#ifndef rb_fd_max
++#if defined(BUILD_FOR_RUBY) && !defined(rb_fd_max)
+ #define fd_check(n) (((n) < FD_SETSIZE) ? 1 : 0*fprintf(stderr, "fd %d too large for select\n", (n)))
+ // These definitions are cribbed from include/ruby/intern.h in Ruby 1.9.3,
+ // with this change: any macros that read or write the nth element of an
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0008-fix-memory-leak-in-_CleanBadDescriptors.patch ruby-eventmachine-1.0.3/debian/patches/0008-fix-memory-leak-in-_CleanBadDescriptors.patch
--- ruby-eventmachine-1.0.3/debian/patches/0008-fix-memory-leak-in-_CleanBadDescriptors.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0008-fix-memory-leak-in-_CleanBadDescriptors.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,24 @@
+From 01e5539bc8580cdef648bc42c0cb23ee54240d27 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 22:40:23 -0800
+Subject: [PATCH 08/11] fix memory leak in _CleanBadDescriptors
+
+---
+ ext/em.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index e2a0e2b..eb4a080 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -975,6 +975,7 @@ void EventMachine_t::_CleanBadDescriptors()
+ 		rb_fd_set(sd, &fds);
+ 
+ 		int ret = rb_fd_select(sd + 1, &fds, NULL, NULL, &tv);
++		rb_fd_term(&fds);
+ 
+ 		if (ret == -1) {
+ 			if (errno == EBADF)
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0009-use-rb_thread_fd_select-whenever-possible.patch ruby-eventmachine-1.0.3/debian/patches/0009-use-rb_thread_fd_select-whenever-possible.patch
--- ruby-eventmachine-1.0.3/debian/patches/0009-use-rb_thread_fd_select-whenever-possible.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0009-use-rb_thread_fd_select-whenever-possible.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,41 @@
+From 5e990ec9429c2a5797567a735452b80a5d6dc6ff Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 23:24:32 -0800
+Subject: [PATCH 09/11] use rb_thread_fd_select whenever possible
+
+Conflicts:
+	ext/em.cpp
+---
+ ext/em.cpp | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index eb4a080..27ea088 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -809,7 +809,8 @@ SelectData_t::~SelectData_t()
+ _SelectDataSelect
+ *****************/
+ 
+-#ifdef HAVE_TBR
++
++#if !defined(HAVE_RB_THREAD_FD_SELECT) && defined(HAVE_TBR)
+ static VALUE _SelectDataSelect (void *v)
+ {
+ 	SelectData_t *sd = (SelectData_t*)v;
+@@ -824,7 +825,11 @@ SelectData_t::_Select
+ 
+ int SelectData_t::_Select()
+ {
+-	#ifdef HAVE_TBR
++	#if defined(HAVE_RB_THREAD_FD_SELECT)
++	// added in ruby 1.9.2
++	return rb_thread_fd_select (maxsocket+1, &fdreads, &fdwrites, &fderrors, &tv);
++	#elif defined(HAVE_TBR)
++	// added in ruby 1.9.1, deprecated in ruby 2.0.0
+ 	rb_thread_blocking_region (_SelectDataSelect, (void*)this, RUBY_UBF_IO, 0);
+ 	return nSockets;
+ 	#endif
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0010-fix-build-on-ruby-1.9.1.patch ruby-eventmachine-1.0.3/debian/patches/0010-fix-build-on-ruby-1.9.1.patch
--- ruby-eventmachine-1.0.3/debian/patches/0010-fix-build-on-ruby-1.9.1.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0010-fix-build-on-ruby-1.9.1.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,69 @@
+From 6c59b07c500b36274788abe47b34103a3a8586a6 Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 23:45:00 -0800
+Subject: [PATCH 10/11] fix build on ruby 1.9.1
+
+Conflicts:
+	ext/extconf.rb
+---
+ ext/em.cpp     | 2 +-
+ ext/em.h       | 9 +++++++--
+ ext/extconf.rb | 2 ++
+ 3 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index 27ea088..315d7d7 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -814,7 +814,7 @@ _SelectDataSelect
+ static VALUE _SelectDataSelect (void *v)
+ {
+ 	SelectData_t *sd = (SelectData_t*)v;
+-	sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
++	sd->nSockets = select (sd->maxsocket+1, rb_fd_ptr(&(sd->fdreads)), rb_fd_ptr(&(sd->fdwrites)), rb_fd_ptr(&(sd->fderrors)), &(sd->tv));
+ 	return Qnil;
+ }
+ #endif
+diff --git a/ext/em.h b/ext/em.h
+index 3799bba..86909ad 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -22,7 +22,12 @@ See the file COPYING for complete licensing information.
+ 
+ #ifdef BUILD_FOR_RUBY
+   #include <ruby.h>
+-  #define EmSelect rb_thread_fd_select
++  #ifdef HAVE_RB_THREAD_FD_SELECT
++    #define EmSelect rb_thread_fd_select
++  #else
++    // ruby 1.9.1 and below
++    #define EmSelect rb_thread_select
++  #endif
+ 
+   #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+     #include <ruby/io.h>
+@@ -60,7 +65,7 @@ See the file COPYING for complete licensing information.
+   #define EmSelect select
+ #endif
+ 
+-#if defined(BUILD_FOR_RUBY) && !defined(rb_fd_max)
++#if defined(BUILD_FOR_RUBY) && !defined(HAVE_RB_FDSET_T)
+ #define fd_check(n) (((n) < FD_SETSIZE) ? 1 : 0*fprintf(stderr, "fd %d too large for select\n", (n)))
+ // These definitions are cribbed from include/ruby/intern.h in Ruby 1.9.3,
+ // with this change: any macros that read or write the nth element of an
+diff --git a/ext/extconf.rb b/ext/extconf.rb
+index 448802a..28cd687 100644
+--- a/ext/extconf.rb
++++ b/ext/extconf.rb
+@@ -70,6 +70,8 @@ add_define "HAVE_TBR" if have_func('rb_thread_blocking_region')# and have_macro(
+ add_define "HAVE_INOTIFY" if inotify = have_func('inotify_init', 'sys/inotify.h')
+ add_define "HAVE_OLD_INOTIFY" if !inotify && have_macro('__NR_inotify_init', 'sys/syscall.h')
+ add_define 'HAVE_WRITEV' if have_func('writev', 'sys/uio.h')
++add_define 'HAVE_RB_THREAD_FD_SELECT' if have_func('rb_thread_fd_select')
++add_define 'HAVE_RB_FDSET_T' if have_type('rb_fdset_t', 'ruby/intern.h')
+ 
+ have_func('rb_wait_for_single_fd')
+ have_func('rb_enable_interrupt')
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/0011-allocate-one-SelectData_t-per-reactor-to-avoid-heap-.patch ruby-eventmachine-1.0.3/debian/patches/0011-allocate-one-SelectData_t-per-reactor-to-avoid-heap-.patch
--- ruby-eventmachine-1.0.3/debian/patches/0011-allocate-one-SelectData_t-per-reactor-to-avoid-heap-.patch	1970-01-01 01:00:00.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/0011-allocate-one-SelectData_t-per-reactor-to-avoid-heap-.patch	2016-07-04 22:00:03.000000000 +0200
@@ -0,0 +1,144 @@
+From 6e75c507e1bb27e44f205a4ee3e1b138bbbff5ab Mon Sep 17 00:00:00 2001
+From: Aman Gupta <aman@tmm1.net>
+Date: Mon, 9 Feb 2015 23:59:11 -0800
+Subject: [PATCH 11/11] allocate one SelectData_t per reactor to avoid heap
+ allocation on every tick
+
+Conflicts:
+	ext/em.cpp
+---
+ ext/em.cpp | 43 ++++++++++++++++++++-----------------------
+ ext/em.h   |  3 ++-
+ 2 files changed, 22 insertions(+), 24 deletions(-)
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index 315d7d7..326dbe8 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -101,6 +101,7 @@ EventMachine_t::EventMachine_t (EMCallback event_callback):
+ 	#endif
+ 
+ 	_InitializeLoopBreaker();
++	SelectData = new SelectData_t();
+ }
+ 
+ 
+@@ -130,6 +131,8 @@ EventMachine_t::~EventMachine_t()
+ 		close (epfd);
+ 	if (kqfd != -1)
+ 		close (kqfd);
++
++	delete SelectData;
+ }
+ 
+ 
+@@ -856,24 +859,18 @@ void EventMachine_t::_RunSelectOnce()
+ 	// epoll will be effective if we provide it as an alternative,
+ 	// however it has the same problem interoperating with Ruby
+ 	// threads that select does.
+-
+-	SelectData_t SelectData;
+-	/*
+-	fd_set fdreads, fdwrites;
+-	FD_ZERO (&fdreads);
+-	FD_ZERO (&fdwrites);
+-
+-	int maxsocket = 0;
+-	*/
++	rb_fd_zero (&SelectData->fdreads);
++	rb_fd_zero (&SelectData->fdwrites);
++	rb_fd_zero (&SelectData->fderrors);
+ 
+ 	// Always read the loop-breaker reader.
+ 	// Changed 23Aug06, provisionally implemented for Windows with a UDP socket
+ 	// running on localhost with a randomly-chosen port. (*Puke*)
+ 	// Windows has a version of the Unix pipe() library function, but it doesn't
+ 	// give you back descriptors that are selectable.
+-	rb_fd_set (LoopBreakerReader, &(SelectData.fdreads));
+-	if (SelectData.maxsocket < LoopBreakerReader)
+-		SelectData.maxsocket = LoopBreakerReader;
++	rb_fd_set (LoopBreakerReader, &(SelectData->fdreads));
++	if (SelectData->maxsocket < LoopBreakerReader)
++		SelectData->maxsocket = LoopBreakerReader;
+ 
+ 	// prepare the sockets for reading and writing
+ 	size_t i;
+@@ -886,27 +883,27 @@ void EventMachine_t::_RunSelectOnce()
+ 		assert (sd != INVALID_SOCKET);
+ 
+ 		if (ed->SelectForRead())
+-			rb_fd_set (sd, &(SelectData.fdreads));
++			rb_fd_set (sd, &(SelectData->fdreads));
+ 		if (ed->SelectForWrite())
+-			rb_fd_set (sd, &(SelectData.fdwrites));
++			rb_fd_set (sd, &(SelectData->fdwrites));
+ 
+ 		#ifdef OS_WIN32
+ 		/* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
+ 		   Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
+ 		*/
+-		rb_fd_set (sd, &(SelectData.fderrors));
++		rb_fd_set (sd, &(SelectData->fderrors));
+ 		#endif
+ 
+-		if (SelectData.maxsocket < sd)
+-			SelectData.maxsocket = sd;
++		if (SelectData->maxsocket < sd)
++			SelectData->maxsocket = sd;
+ 	}
+ 
+ 
+ 	{ // read and write the sockets
+ 		//timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000.
+ 		//timeval tv = Quantum;
+-		SelectData.tv = _TimeTilNextEvent();
+-		int s = SelectData._Select();
++		SelectData->tv = _TimeTilNextEvent();
++		int s = SelectData->_Select();
+ 		//rb_thread_blocking_region(xxx,(void*)&SelectData,RUBY_UBF_IO,0);
+ 		//int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads), &(SelectData.fdwrites), NULL, &(SelectData.tv));
+ 		//int s = SelectData.nSockets;
+@@ -929,15 +926,15 @@ void EventMachine_t::_RunSelectOnce()
+ 					continue;
+ 				assert (sd != INVALID_SOCKET);
+ 
+-				if (rb_fd_isset (sd, &(SelectData.fdwrites)))
++				if (rb_fd_isset (sd, &(SelectData->fdwrites)))
+ 					ed->Write();
+-				if (rb_fd_isset (sd, &(SelectData.fdreads)))
++				if (rb_fd_isset (sd, &(SelectData->fdreads)))
+ 					ed->Read();
+-				if (rb_fd_isset (sd, &(SelectData.fderrors)))
++				if (rb_fd_isset (sd, &(SelectData->fderrors)))
+ 					ed->HandleError();
+ 			}
+ 
+-			if (rb_fd_isset (LoopBreakerReader, &(SelectData.fdreads)))
++			if (rb_fd_isset (LoopBreakerReader, &(SelectData->fdreads)))
+ 				_ReadLoopBreaker();
+ 		}
+ 		else if (s < 0) {
+diff --git a/ext/em.h b/ext/em.h
+index 86909ad..cdcca23 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -91,7 +91,7 @@ typedef fd_set rb_fdset_t;
+ 
+ class EventableDescriptor;
+ class InotifyDescriptor;
+-
++struct SelectData_t;
+ 
+ /********************
+ class EventMachine_t
+@@ -234,6 +234,7 @@ class EventMachine_t
+ 
+ 	private:
+ 		bool bTerminateSignalReceived;
++		SelectData_t *SelectData;
+ 
+ 		bool bEpoll;
+ 		int epfd; // Epoll file-descriptor
+-- 
+2.1.4
+
diff -Nru ruby-eventmachine-1.0.3/debian/patches/series ruby-eventmachine-1.0.3/debian/patches/series
--- ruby-eventmachine-1.0.3/debian/patches/series	2014-01-21 22:32:58.000000000 +0100
+++ ruby-eventmachine-1.0.3/debian/patches/series	2016-07-04 22:00:03.000000000 +0200
@@ -1 +1,12 @@
 skip_tests_using_network.patch
+0001-use-ruby-select-api-with-expandable-fd-sets.patch
+0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch
+0003-add-comment-about-where-the-macros-came-from.patch
+0004-must-call-raw-select-from-thread_blocking_region.patch
+0005-epoll-kqueue-on-older-rubies-without-rb_wait_for_sin.patch
+0006-make-sure-to-clean-up-rb_fd_init-memory-during-shutd.patch
+0007-keep-BUILD_FOR_RUBY-compat.patch
+0008-fix-memory-leak-in-_CleanBadDescriptors.patch
+0009-use-rb_thread_fd_select-whenever-possible.patch
+0010-fix-build-on-ruby-1.9.1.patch
+0011-allocate-one-SelectData_t-per-reactor-to-avoid-heap-.patch

Reply to: