summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-09-12 11:41:30 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-09-12 11:41:30 +0000
commit167f6b291f4cf697048af42820c82d8cf357e0a7 (patch)
tree750e7c085bad1a44d7856f5d650ae3a5c7a75f61
parente0eaa117d2bae9968258ec0e14bab667998abe66 (diff)
merge revision(s) 33256:
* thread.c (rb_thread_select): fix to ignore an argument modification of rb_thread_fd_select(). based on a patch by Eric Wong. [Bug #5306] [ruby-core:39435] * thread.c (rb_fd_rcopy): New. for reverse fd copy. * test/-ext-/old_thread_select/test_old_thread_select.rb (test_old_select_false_positive): test for bug5306. * ext/-test-/old_thread_select/old_thread_select.c (fdset2array): New. convert fdsets to array. * ext/-test-/old_thread_select/old_thread_select.c (old_thread_select): return 'read', 'write', 'except' argument of rb_thread_select() to ruby script. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_3@33257 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog16
-rw-r--r--ext/-test-/old_thread_select/old_thread_select.c19
-rw-r--r--test/-ext-/old_thread_select/test_old_thread_select.rb14
-rw-r--r--thread.c38
-rw-r--r--version.h4
5 files changed, 86 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index ea910d2768..2869b80ddf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Mon Sep 12 20:41:20 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * thread.c (rb_thread_select): fix to ignore an argument
+ modification of rb_thread_fd_select().
+ based on a patch by Eric Wong. [Bug #5306] [ruby-core:39435]
+ * thread.c (rb_fd_rcopy): New. for reverse fd copy.
+
+ * test/-ext-/old_thread_select/test_old_thread_select.rb
+ (test_old_select_false_positive): test for bug5306.
+
+ * ext/-test-/old_thread_select/old_thread_select.c (fdset2array):
+ New. convert fdsets to array.
+ * ext/-test-/old_thread_select/old_thread_select.c (old_thread_select):
+ return 'read', 'write', 'except' argument of rb_thread_select()
+ to ruby script.
+
Tue Sep 6 13:15:44 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
* encoding.c (load_encoding): predefined encoding names are safe.
diff --git a/ext/-test-/old_thread_select/old_thread_select.c b/ext/-test-/old_thread_select/old_thread_select.c
index 881cb7db9f..e374f02355 100644
--- a/ext/-test-/old_thread_select/old_thread_select.c
+++ b/ext/-test-/old_thread_select/old_thread_select.c
@@ -25,6 +25,18 @@ static fd_set * array2fdset(fd_set *fds, VALUE ary, int *max)
return fds;
}
+static void fdset2array(VALUE dst, fd_set *fds, int max)
+{
+ int i;
+
+ rb_ary_clear(dst);
+
+ for (i = 0; i < max; i++) {
+ if (FD_ISSET(i, fds))
+ rb_ary_push(dst, INT2NUM(i));
+ }
+}
+
static VALUE
old_thread_select(VALUE klass, VALUE r, VALUE w, VALUE e, VALUE timeout)
{
@@ -45,6 +57,13 @@ old_thread_select(VALUE klass, VALUE r, VALUE w, VALUE e, VALUE timeout)
rc = rb_thread_select(max, rp, wp, ep, tvp);
if (rc == -1)
rb_sys_fail("rb_wait_for_single_fd");
+
+ if (rp)
+ fdset2array(r, &rfds, max);
+ if (wp)
+ fdset2array(w, &wfds, max);
+ if (ep)
+ fdset2array(e, &efds, max);
return INT2NUM(rc);
}
diff --git a/test/-ext-/old_thread_select/test_old_thread_select.rb b/test/-ext-/old_thread_select/test_old_thread_select.rb
index a7db7bdf99..18235b845a 100644
--- a/test/-ext-/old_thread_select/test_old_thread_select.rb
+++ b/test/-ext-/old_thread_select/test_old_thread_select.rb
@@ -23,6 +23,20 @@ class TestOldThreadSelect < Test::Unit::TestCase
end
end
+ def test_old_select_false_positive
+ bug5306 = '[ruby-core:39435]'
+ with_pipe do |r2, w2|
+ with_pipe do |r, w|
+ t0 = Time.now
+ w.syswrite '.'
+ rfds = [ r.fileno, r2.fileno ]
+ rc = IO.old_thread_select(rfds, nil, nil, nil)
+ assert_equal [ r.fileno ], rfds, bug5306
+ assert_equal 1, rc, bug5306
+ end
+ end
+ end
+
def test_old_select_read_write_check
with_pipe do |r, w|
w.syswrite('.')
diff --git a/thread.c b/thread.c
index 28eece555d..192b696629 100644
--- a/thread.c
+++ b/thread.c
@@ -2391,6 +2391,17 @@ rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
memcpy(dst->fdset, src, size);
}
+static void
+rb_fd_rcopy(fd_set *dst, rb_fdset_t *src)
+{
+ size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
+
+ if (size > sizeof(fd_set)) {
+ rb_raise(rb_eArgError, "too large fdsets");
+ }
+ memcpy(dst, rb_fd_ptr(src), sizeof(fd_set));
+}
+
void
rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
{
@@ -2449,6 +2460,19 @@ rb_fd_init_copy(rb_fdset_t *dst, rb_fdset_t *src)
rb_fd_dup(dst, src);
}
+static void
+rb_fd_rcopy(fd_set *dst, rb_fdset_t *src)
+{
+ int max = rb_fd_max(src);
+
+ if (max > FD_SETSIZE) {
+ rb_raise(rb_eArgError, "too large fdsets");
+ }
+
+ memcpy(dst->fd_array, src->fdset->fd_array, max);
+ dst->fd_count = max;
+}
+
void
rb_fd_term(rb_fdset_t *set)
{
@@ -2485,6 +2509,8 @@ rb_fd_set(int fd, rb_fdset_t *set)
#define FD_CLR(i, f) rb_fd_clr((i), (f))
#define FD_ISSET(i, f) rb_fd_isset((i), (f))
+#else
+#define rb_fd_rcopy(d, s) (*(d) = *(s))
#endif
#if defined(__CYGWIN__)
@@ -2706,12 +2732,18 @@ rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
retval = rb_thread_fd_select(max, rfds, wfds, efds, timeout);
- if (rfds)
+ if (rfds) {
+ rb_fd_rcopy(read, rfds);
rb_fd_term(rfds);
- if (wfds)
+ }
+ if (wfds) {
+ rb_fd_rcopy(write, wfds);
rb_fd_term(wfds);
- if (efds)
+ }
+ if (efds) {
+ rb_fd_rcopy(except, efds);
rb_fd_term(efds);
+ }
return retval;
}
diff --git a/version.h b/version.h
index f5e69df674..4e573bac1e 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "1.9.3"
#define RUBY_PATCHLEVEL -1
-#define RUBY_RELEASE_DATE "2011-09-11"
+#define RUBY_RELEASE_DATE "2011-09-12"
#define RUBY_RELEASE_YEAR 2011
#define RUBY_RELEASE_MONTH 9
-#define RUBY_RELEASE_DAY 11
+#define RUBY_RELEASE_DAY 12
#include "ruby/version.h"