[前][次][番号順一覧][スレッド一覧]

ruby-changes:21068

From: kosaki <ko1@a...>
Date: Tue, 30 Aug 2011 09:33:16 +0900 (JST)
Subject: [ruby-changes:21068] kosaki:r33117 (trunk): * thread.c (rb_thread_select): rewrite by using

kosaki	2011-08-30 09:33:05 +0900 (Tue, 30 Aug 2011)

  New Revision: 33117

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33117

  Log:
    * thread.c (rb_thread_select): rewrite by using
      rb_thread_fd_select(). old one is EINTR unsafe.
      Patch by Eric Wong. [Bug #5229] [ruby-core:39102]
    
    * test/-ext-/old_thread_select/test_old_thread_select.rb:
      a testcase for rb_thread_select().
    * ext/-test-/old_thread_select/old_thread_select.c: ditto.
    * ext/-test-/old_thread_select/depend: ditto.
    * ext/-test-/old_thread_select/extconf.rb: ditto.

  Added directories:
    trunk/ext/-test-/old_thread_select/
    trunk/test/-ext-/old_thread_select/
  Added files:
    trunk/ext/-test-/old_thread_select/depend
    trunk/ext/-test-/old_thread_select/extconf.rb
    trunk/ext/-test-/old_thread_select/old_thread_select.c
    trunk/test/-ext-/old_thread_select/test_old_thread_select.rb
  Modified files:
    trunk/ChangeLog
    trunk/thread.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 33116)
+++ ChangeLog	(revision 33117)
@@ -1,3 +1,15 @@
+Tue Aug 30 09:28:01 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* thread.c (rb_thread_select): rewrite by using
+	  rb_thread_fd_select(). old one is EINTR unsafe.
+	  Patch by Eric Wong. [Bug #5229] [ruby-core:39102]
+	
+	* test/-ext-/old_thread_select/test_old_thread_select.rb:
+	  a testcase for rb_thread_select().
+	* ext/-test-/old_thread_select/old_thread_select.c: ditto.
+	* ext/-test-/old_thread_select/depend: ditto.
+	* ext/-test-/old_thread_select/extconf.rb: ditto.
+
 Tue Aug 30 09:08:22 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* configure.in: fix a build failure on GNU Hurd.
Index: thread.c
===================================================================
--- thread.c	(revision 33116)
+++ thread.c	(revision 33117)
@@ -2686,30 +2686,37 @@
 rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
 		 struct timeval *timeout)
 {
-    if (!read && !write && !except) {
-	if (!timeout) {
-	    rb_thread_sleep_forever();
-	    return 0;
-	}
-	rb_thread_wait_for(*timeout);
-	return 0;
+    rb_fdset_t fdsets[3] = { 0 };
+    rb_fdset_t *rfds = NULL;
+    rb_fdset_t *wfds = NULL;
+    rb_fdset_t *efds = NULL;
+    int retval;
+
+    if (read) {
+	rfds = &fdsets[0];
+	rb_fd_copy(rfds, read, max);
     }
-    else {
-	int lerrno = errno;
-	int result;
+    if (write) {
+	wfds = &fdsets[1];
+	rb_fd_copy(wfds, write, max);
+    }
+    if (except) {
+	efds = &fdsets[2];
+	rb_fd_copy(efds, except, max);
+    }
 
-	BLOCKING_REGION({
-		result = select(max, read, write, except, timeout);
-		if (result < 0)
-		    lerrno = errno;
-	    }, ubf_select, GET_THREAD());
-	errno = lerrno;
+    retval = rb_thread_fd_select(max, rfds, efds, wfds, timeout);
 
-	return result;
-    }
+    if (rfds)
+	rb_fd_term(rfds);
+    if (wfds)
+	rb_fd_term(wfds);
+    if (efds)
+	rb_fd_term(efds);
+
+    return retval;
 }
 
-
 int
 rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * except,
 		    struct timeval *timeout)
Index: ext/-test-/old_thread_select/depend
===================================================================
--- ext/-test-/old_thread_select/depend	(revision 0)
+++ ext/-test-/old_thread_select/depend	(revision 33117)
@@ -0,0 +1,2 @@
+old_thread_select.o: $(top_srcdir)/thread.c \
+  $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/io.h

Property changes on: ext/-test-/old_thread_select/depend
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/-test-/old_thread_select/old_thread_select.c
===================================================================
--- ext/-test-/old_thread_select/old_thread_select.c	(revision 0)
+++ ext/-test-/old_thread_select/old_thread_select.c	(revision 33117)
@@ -0,0 +1,56 @@
+/* test case for deprecated C API */
+#include "ruby/ruby.h"
+#include "ruby/io.h"
+
+static fd_set * array2fdset(fd_set *fds, VALUE ary, int *max)
+{
+    long i;
+
+    if (NIL_P(ary))
+	return NULL;
+
+    FD_ZERO(fds);
+    Check_Type(ary, T_ARRAY);
+    for (i = 0; i < RARRAY_LEN(ary); i++) {
+	VALUE val = RARRAY_PTR(ary)[i];
+	int fd;
+
+	Check_Type(val, T_FIXNUM);
+	fd = FIX2INT(val);
+	if (fd >= *max)
+	    *max = fd + 1;
+	FD_SET(fd, fds);
+    }
+
+    return fds;
+}
+
+static VALUE
+old_thread_select(VALUE klass, VALUE r, VALUE w, VALUE e, VALUE timeout)
+{
+    struct timeval tv;
+    struct timeval *tvp = NULL;
+    fd_set rfds, wfds, efds;
+    fd_set *rp, *wp, *ep;
+    int rc;
+    int max = 0;
+
+    if (!NIL_P(timeout)) {
+	tv = rb_time_timeval(timeout);
+	tvp = &tv;
+    }
+    rp = array2fdset(&rfds, r, &max);
+    wp = array2fdset(&wfds, w, &max);
+    ep = array2fdset(&efds, w, &max);
+    rc = rb_thread_select(max, rp, wp, ep, tvp);
+    if (rc == -1)
+	rb_sys_fail("rb_wait_for_single_fd");
+    return INT2NUM(rc);
+}
+
+void
+Init_old_thread_select(void)
+{
+    rb_define_singleton_method(rb_cIO, "old_thread_select",
+                               old_thread_select, 4);
+}

Property changes on: ext/-test-/old_thread_select/old_thread_select.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/-test-/old_thread_select/extconf.rb
===================================================================
--- ext/-test-/old_thread_select/extconf.rb	(revision 0)
+++ ext/-test-/old_thread_select/extconf.rb	(revision 33117)
@@ -0,0 +1 @@
+create_makefile("-test-/old_thread_select/old_thread_select")

Property changes on: ext/-test-/old_thread_select/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/-ext-/old_thread_select/test_old_thread_select.rb
===================================================================
--- test/-ext-/old_thread_select/test_old_thread_select.rb	(revision 0)
+++ test/-ext-/old_thread_select/test_old_thread_select.rb	(revision 33117)
@@ -0,0 +1,69 @@
+require 'test/unit'
+
+class TestOldThreadSelect < Test::Unit::TestCase
+  require '-test-/old_thread_select/old_thread_select'
+
+  def with_pipe
+    r, w = IO.pipe
+    begin
+      yield r, w
+    ensure
+      r.close unless r.closed?
+      w.close unless w.closed?
+    end
+  end
+
+  def test_old_select_read_timeout
+    with_pipe do |r, w|
+      t0 = Time.now
+      rc = IO.old_thread_select([r.fileno], nil, nil, 0.001)
+      diff = Time.now - t0
+      assert_equal 0, rc
+      assert diff > 0.001, "returned too early"
+    end
+  end
+
+  def test_old_select_read_write_check
+    with_pipe do |r, w|
+      w.syswrite('.')
+      rc = IO.old_thread_select([r.fileno], nil, nil, nil)
+      assert_equal 1, rc
+
+      rc = IO.old_thread_select([r.fileno], [w.fileno], nil, nil)
+      assert_equal 2, rc
+
+      assert_equal '.', r.read(1)
+
+      rc = IO.old_thread_select([r.fileno], [w.fileno], nil, nil)
+      assert_equal 1, rc
+    end
+  end
+
+  def test_old_select_signal_safe
+    return unless Process.respond_to?(:kill)
+    usr1 = false
+    trap(:USR1) { usr1 = true }
+    main = Thread.current
+    thr = Thread.new do
+      Thread.pass until main.stop?
+      Process.kill(:USR1, $$)
+      true
+    end
+
+    rc = nil
+    t0 = Time.now
+    with_pipe do |r,w|
+      assert_nothing_raised do
+        rc = IO.old_thread_select([r.fileno], nil, nil, 1)
+      end
+    end
+
+    diff = Time.now - t0
+    assert diff >= 1.0, "interrupted or short wait"
+    assert_equal 0, rc
+    assert_equal true, thr.value
+    assert usr1, "USR1 not received"
+    ensure
+      trap(:USR1, "DEFAULT")
+  end
+end

Property changes on: test/-ext-/old_thread_select/test_old_thread_select.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]