io_splice 4.1.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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