io_splice 4.1.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v4.1.0.GIT
4
+ DEF_VER=v4.1.1.GIT
5
5
 
6
6
  LF='
7
7
  '
@@ -217,9 +217,9 @@ static ssize_t do_splice(int argc, VALUE *argv, unsigned dflags)
217
217
  * into account userspace buffering done by Ruby or stdio. It is
218
218
  * also not subject to encoding/decoding filters under Ruby 1.9.
219
219
  *
220
- * Consider using IO.trysplice if you are using non-blocking I/O on
221
- * both descriptors as it avoids the cost of raising common Errno::EAGAIN
222
- * exceptions.
220
+ * Consider using IO.trysplice if +io_out+ is a pipe or if you are using
221
+ * non-blocking I/O on both descriptors as it avoids the cost of raising
222
+ * common Errno::EAGAIN exceptions.
223
223
  *
224
224
  * See manpage for full documentation:
225
225
  * http://kernel.org/doc/man-pages/online/pages/man2/splice.2.html
@@ -247,6 +247,8 @@ static VALUE my_splice(int argc, VALUE *argv, VALUE self)
247
247
  * but this can still block if the non-pipe descriptor is blocking.
248
248
  *
249
249
  * See IO.splice documentation for more details.
250
+ *
251
+ * This method is recommended whenever +io_out+ is a pipe.
250
252
  */
251
253
  static VALUE trysplice(int argc, VALUE *argv, VALUE self)
252
254
  {
@@ -639,6 +641,12 @@ void Init_io_splice_ext(void)
639
641
  * themselves are ignored by this family of functions, and
640
642
  * using this flag is the only way to get non-blocking operation
641
643
  * out of them.
644
+ *
645
+ * It is highly recommended this flag be set (or IO.trysplice used)
646
+ * whenever splicing from a socket into a pipe unless there is
647
+ * another (native) thread or process doing a blocking read on that
648
+ * pipe. Otherwise it is possible to block a single-threaded process
649
+ * if the socket buffers are larger than the pipe buffers.
642
650
  */
643
651
  rb_define_const(mSplice, "F_NONBLOCK", UINT2NUM(SPLICE_F_NONBLOCK));
644
652
  assert(WAITALL != SPLICE_F_NONBLOCK && "WAITALL == F_NONBLOCK");
@@ -84,6 +84,13 @@ module IO::Splice
84
84
  # This will block and wait for IO completion of +len+
85
85
  # Raises +EOFError+ if end of file is reached.
86
86
  # bytes. Returns the number of bytes actually spliced (always +len+)
87
+ # unless +src+ does not have +len+ bytes to read.
88
+ #
89
+ # Do not use this method to splice a socket +src+ into a pipe +dst+
90
+ # unless there is another process or native thread doing a blocking
91
+ # read on the other end of the +dst+ pipe.
92
+ #
93
+ # This method is safe for splicing a pipe +src+ into any type of +dst+ IO.
87
94
  def self.full(src, dst, len, src_offset)
88
95
  IO.splice(src, src_offset, dst, nil, len, F_MOVE | WAITALL)
89
96
  end
@@ -94,16 +101,15 @@ module IO::Splice
94
101
  # Returns the number of bytes actually spliced.
95
102
  # Like IO#readpartial, this never returns Errno::EAGAIN
96
103
  def self.partial(src, dst, len, src_offset)
97
- IO.splice(src, src_offset, dst, nil, len, F_MOVE)
98
- rescue EOFError
99
- nil
100
- rescue Errno::EAGAIN
101
- begin
102
- src.to_io.wait
103
- IO.select(nil, [dst])
104
- rv = IO.trysplice(src, src_offset, dst, nil, len, F_MOVE)
105
- end while rv == :EAGAIN
106
- rv
104
+ case rv = IO.trysplice(src, src_offset, dst, nil, len, F_MOVE)
105
+ when :EAGAIN
106
+ src.to_io.wait
107
+ IO.select(nil, [dst])
108
+ when Integer
109
+ return rv
110
+ else
111
+ return nil
112
+ end while true
107
113
  end
108
114
  end
109
115
  if (! defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") &&
@@ -0,0 +1,49 @@
1
+ require 'socket'
2
+ require 'io/wait'
3
+ require 'io/splice'
4
+ require 'io/nonblock'
5
+ require "test/unit"
6
+
7
+ class TestTCPCopyStream < Test::Unit::TestCase
8
+ def setup
9
+ host = ENV["TEST_HOST"] || "127.0.0.1"
10
+ @srv = TCPServer.new(host, 0)
11
+ @port = @srv.addr[1]
12
+ @client = TCPSocket.new(host, @port)
13
+ @client.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
14
+ @accept = @srv.accept
15
+ @accept.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
16
+ @client.sync = @accept.sync = true
17
+ @r, @w = IO.pipe
18
+ end
19
+
20
+ def teardown
21
+ @srv.close
22
+ [ @client, @accept, @r, @w ].each { |io| io.close unless io.closed? }
23
+ end
24
+
25
+ def test_client_to_server_eof
26
+ nr = 2000
27
+ buf = '0123456789abcdef' * 1024
28
+ expect = buf.size * nr
29
+ thr = Thread.new do
30
+ nr.times { @client.write(buf) }
31
+ @client.close
32
+ end
33
+ sleep 1 # wait for rcvbuf to fill up
34
+ bytes = IO::Splice.copy_stream(@accept, "/dev/null")
35
+ assert_equal expect, bytes
36
+ end
37
+
38
+ def test_client_to_server_expect
39
+ nr = 2000
40
+ buf = '0123456789abcdef' * 1024
41
+ expect = buf.size * nr
42
+ thr = Thread.new do
43
+ nr.times { @client.write(buf) }
44
+ end
45
+ sleep 1 # wait for rcvbuf to fill up
46
+ bytes = IO::Splice.copy_stream(@accept, "/dev/null", expect)
47
+ assert_equal expect, bytes
48
+ end
49
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io_splice
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 57
5
5
  prerelease:
6
6
  segments:
7
7
  - 4
8
8
  - 1
9
- - 0
10
- version: 4.1.0
9
+ - 1
10
+ version: 4.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ruby io_splice hackers
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-16 00:00:00 Z
18
+ date: 2011-05-18 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: wrongdoc
@@ -96,6 +96,7 @@ files:
96
96
  - test/test_io_splice_eintr.rb
97
97
  - test/test_io_splice_in_full.rb
98
98
  - test/test_rack_file_compat.rb
99
+ - test/test_tcp_splice.rb
99
100
  homepage: http://bogomips.org/ruby_io_splice/
100
101
  licenses: []
101
102
 
@@ -135,6 +136,7 @@ summary: zero-copy pipe I/O for Linux and Ruby
135
136
  test_files:
136
137
  - test/test_rack_file_compat.rb
137
138
  - test/test_io_splice_in_full.rb
139
+ - test/test_tcp_splice.rb
138
140
  - test/test_io_splice.rb
139
141
  - test/test_copy_stream.rb
140
142
  - test/test_io_splice_eintr.rb