Package: release.debian.org Severity: normal Tags: jessie User: release.debian....@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 <bal...@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.reyno...@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.reyno...@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.reyno...@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 <a...@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 <a...@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 <a...@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 <a...@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 <a...@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 <a...@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 <a...@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 <a...@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