0001-thread.c-rb_thread_select-implement-using-rb_thread_.patch

Eric Wong, 08/25/2011 08:33 AM

Download (6.28 KB)

View differences:

ext/-test-/old_thread_select/depend
1
old_thread_select.o: $(top_srcdir)/thread.c \
2
  $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/io.h
ext/-test-/old_thread_select/extconf.rb
1
create_makefile("-test-/old_thread_select/old_thread_select")
ext/-test-/old_thread_select/old_thread_select.c
1
/* test case for deprecated C API */
2
#include "ruby/ruby.h"
3
#include "ruby/io.h"
4

  
5
static fd_set * array2fdset(fd_set *fds, VALUE ary, int *max)
6
{
7
    long i;
8

  
9
    if (NIL_P(ary))
10
	return NULL;
11

  
12
    FD_ZERO(fds);
13
    Check_Type(ary, T_ARRAY);
14
    for (i = 0; i < RARRAY_LEN(ary); i++) {
15
	VALUE val = RARRAY_PTR(ary)[i];
16
	int fd;
17

  
18
	Check_Type(val, T_FIXNUM);
19
	fd = FIX2INT(val);
20
	if (fd >= *max)
21
	    *max = fd + 1;
22
	FD_SET(fd, fds);
23
    }
24

  
25
    return fds;
26
}
27

  
28
static VALUE
29
old_thread_select(VALUE klass, VALUE r, VALUE w, VALUE e, VALUE timeout)
30
{
31
    struct timeval tv;
32
    struct timeval *tvp = NULL;
33
    fd_set rfds, wfds, efds;
34
    fd_set *rp, *wp, *ep;
35
    int rc;
36
    int max = 0;
37

  
38
    if (!NIL_P(timeout)) {
39
	tv = rb_time_timeval(timeout);
40
	tvp = &tv;
41
    }
42
    rp = array2fdset(&rfds, r, &max);
43
    wp = array2fdset(&wfds, w, &max);
44
    ep = array2fdset(&efds, w, &max);
45
    rc = rb_thread_select(max, rp, wp, ep, tvp);
46
    if (rc == -1)
47
	rb_sys_fail("rb_wait_for_single_fd");
48
    return INT2NUM(rc);
49
}
50

  
51
void
52
Init_old_thread_select(void)
53
{
54
    rb_define_singleton_method(rb_cIO, "old_thread_select",
55
                               old_thread_select, 4);
56
}
test/-ext-/old_thread_select/test_old_thread_select.rb
1
require 'test/unit'
2

  
3
class TestOldThreadSelect < Test::Unit::TestCase
4
  require '-test-/old_thread_select/old_thread_select'
5

  
6
  def with_pipe
7
    r, w = IO.pipe
8
    begin
9
      yield r, w
10
    ensure
11
      r.close unless r.closed?
12
      w.close unless w.closed?
13
    end
14
  end
15

  
16
  def test_old_select_read_timeout
17
    with_pipe do |r, w|
18
      t0 = Time.now
19
      rc = IO.old_thread_select([r.fileno], nil, nil, 0.001)
20
      diff = Time.now - t0
21
      assert_equal 0, rc
22
      assert diff > 0.001, "returned too early"
23
    end
24
  end
25

  
26
  def test_old_select_read_write_check
27
    with_pipe do |r, w|
28
      w.syswrite('.')
29
      rc = IO.old_thread_select([r.fileno], nil, nil, nil)
30
      assert_equal 1, rc
31

  
32
      rc = IO.old_thread_select([r.fileno], [w.fileno], nil, nil)
33
      assert_equal 2, rc
34

  
35
      assert_equal '.', r.read(1)
36

  
37
      rc = IO.old_thread_select([r.fileno], [w.fileno], nil, nil)
38
      assert_equal 1, rc
39
    end
40
  end
41

  
42
  def test_old_select_signal_safe
43
    return unless Process.respond_to?(:kill)
44
    usr1 = false
45
    trap(:USR1) { usr1 = true }
46
    main = Thread.current
47
    thr = Thread.new do
48
      Thread.pass until main.stop?
49
      Process.kill(:USR1, $$)
50
      true
51
    end
52

  
53
    rc = nil
54
    t0 = Time.now
55
    with_pipe do |r,w|
56
      assert_nothing_raised do
57
        rc = IO.old_thread_select([r.fileno], nil, nil, 1)
58
      end
59
    end
60

  
61
    diff = Time.now - t0
62
    assert diff >= 1.0, "interrupted or short wait"
63
    assert_equal 0, rc
64
    assert_equal true, thr.value
65
    assert usr1, "USR1 not received"
66
    ensure
67
      trap(:USR1, "DEFAULT")
68
  end
69
end
thread.c
2686 2686
rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
2687 2687
		 struct timeval *timeout)
2688 2688
{
2689
    if (!read && !write && !except) {
2690
	if (!timeout) {
2691
	    rb_thread_sleep_forever();
2692
	    return 0;
2693
	}
2694
	rb_thread_wait_for(*timeout);
2695
	return 0;
2689
    rb_fdset_t fdsets[3] = { 0 };
2690
    rb_fdset_t *rfds = NULL;
2691
    rb_fdset_t *wfds = NULL;
2692
    rb_fdset_t *efds = NULL;
2693
    int retval;
2694

  
2695
    if (read) {
2696
	rfds = &fdsets[0];
2697
	rb_fd_copy(rfds, read, max);
2698
    }
2699
    if (write) {
2700
	wfds = &fdsets[1];
2701
	rb_fd_copy(wfds, write, max);
2702
    }
2703
    if (except) {
2704
	efds = &fdsets[2];
2705
	rb_fd_copy(efds, except, max);
2696 2706
    }
2697
    else {
2698
	int lerrno = errno;
2699
	int result;
2700 2707

  
2701
	BLOCKING_REGION({
2702
		result = select(max, read, write, except, timeout);
2703
		if (result < 0)
2704
		    lerrno = errno;
2705
	    }, ubf_select, GET_THREAD());
2706
	errno = lerrno;
2708
    retval = rb_thread_fd_select(max, rfds, efds, wfds, timeout);
2707 2709

  
2708
	return result;
2709
    }
2710
}
2710
    if (rfds)
2711
	rb_fd_term(rfds);
2712
    if (wfds)
2713
	rb_fd_term(wfds);
2714
    if (efds)
2715
	rb_fd_term(efds);
2711 2716

  
2717
    return retval;
2718
}
2712 2719

  
2713 2720
int
2714 2721
rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * except,