set close-on-exec in pipe size modification check
[ruby_io_splice.git] / ext / io_splice / io_splice_ext.c
blob1c938c36eed25dc6ddabb56fd193dd8a31288e55
1 #include "ruby.h"
2 #ifdef HAVE_RUBY_IO_H
3 # include "ruby/io.h"
4 #else
5 # include "rubyio.h"
6 #endif
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <assert.h>
10 #include <sys/uio.h>
11 #include <limits.h>
12 #include <alloca.h>
13 #include <unistd.h>
15 static VALUE sym_EAGAIN;
16 #define WAITALL 0x4000000
18 /* taken from haproxy */
19 #define MAX_AT_ONCE (1 << 30)
21 #ifndef F_LINUX_SPECIFIC_BASE
22 # define F_LINUX_SPECIFIC_BASE 1024
23 #endif
25 #ifndef F_GETPIPE_SZ
26 # define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
27 # define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
28 #endif
30 #if ! HAVE_RB_IO_T
31 # define rb_io_t OpenFile
32 #endif
34 #ifdef GetReadFile
35 # define FPTR_TO_FD(fptr) (fileno(GetReadFile(fptr)))
36 #else
37 # if !HAVE_RB_IO_T || (RUBY_VERSION_MAJOR == 1 && RUBY_VERSION_MINOR == 8)
38 # define FPTR_TO_FD(fptr) fileno(fptr->f)
39 # else
40 # define FPTR_TO_FD(fptr) fptr->fd
41 # endif
42 #endif
44 #ifndef SSIZET2NUM
45 # define SSIZET2NUM(x) LONG2NUM(x)
46 #endif
47 #ifndef NUM2SSIZET
48 # define NUM2SSIZET(x) NUM2LONG(x)
49 #endif
50 #ifndef SIZET2NUM
51 # define SIZET2NUM(x) ULONG2NUM(x)
52 #endif
53 #ifndef NUM2SIZET
54 # define NUM2SIZET(x) NUM2ULONG(x)
55 #endif
57 static int my_fileno(VALUE io)
59 rb_io_t *fptr;
61 for (;;) {
62 switch (TYPE(io)) {
63 case T_FIXNUM: return FIX2INT(io);
64 case T_FILE: {
65 GetOpenFile(io, fptr);
66 return FPTR_TO_FD(fptr);
68 default:
69 io = rb_convert_type(io, T_FILE, "IO", "to_io");
70 /* retry */
75 static int check_fileno(VALUE io)
77 int saved_errno = errno;
78 int fd = my_fileno(io);
79 errno = saved_errno;
80 return fd;
82 #ifndef HAVE_RB_THREAD_BLOCKING_REGION
83 /* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
84 # include <rubysig.h>
85 # define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
86 typedef void rb_unblock_function_t(void *);
87 typedef VALUE rb_blocking_function_t(void *);
88 static VALUE
89 rb_thread_blocking_region(
90 rb_blocking_function_t *fn, void *data1,
91 rb_unblock_function_t *ubf, void *data2)
93 VALUE rv;
95 assert(RUBY_UBF_IO == ubf && "RUBY_UBF_IO required for emulation");
97 TRAP_BEG;
98 rv = fn(data1);
99 TRAP_END;
101 return rv;
103 #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
105 #ifndef RSTRING_PTR
106 # define RSTRING_PTR(s) (RSTRING(s)->ptr)
107 #endif
108 #ifndef RSTRING_LEN
109 # define RSTRING_LEN(s) (RSTRING(s)->len)
110 #endif
111 #ifndef RARRAY_PTR
112 # define RARRAY_PTR(s) (RARRAY(s)->ptr)
113 #endif
114 #ifndef RARRAY_LEN
115 # define RARRAY_LEN(s) (RARRAY(s)->len)
116 #endif
118 static VALUE io_run(rb_blocking_function_t *fn, void *data)
120 return rb_thread_blocking_region(fn, data, RUBY_UBF_IO, 0);
123 struct splice_args {
124 int fd_in;
125 off_t *off_in;
126 int fd_out;
127 off_t *off_out;
128 size_t len;
129 unsigned flags;
132 static VALUE nogvl_splice(void *ptr)
134 struct splice_args *a = ptr;
136 if (a->len > MAX_AT_ONCE)
137 a->len = MAX_AT_ONCE;
139 return (VALUE)splice(a->fd_in, a->off_in, a->fd_out, a->off_out,
140 a->len, a->flags);
143 static ssize_t do_splice(int argc, VALUE *argv, unsigned dflags)
145 off_t i = 0, o = 0;
146 VALUE io_in, off_in, io_out, off_out, len, flags;
147 struct splice_args a;
148 ssize_t bytes;
149 ssize_t total = 0;
150 unsigned waitall;
152 rb_scan_args(argc, argv, "51",
153 &io_in, &off_in, &io_out, &off_out, &len, &flags);
155 a.off_in = NIL_P(off_in) ? NULL : (i = NUM2OFFT(off_in), &i);
156 a.off_out = NIL_P(off_out) ? NULL : (o = NUM2OFFT(off_out), &o);
157 a.len = NUM2SIZET(len);
158 a.flags = NIL_P(flags) ? dflags : NUM2UINT(flags) | dflags;
159 waitall = a.flags & WAITALL;
160 if (waitall)
161 a.flags ^= WAITALL;
163 for (;;) {
164 a.fd_in = check_fileno(io_in);
165 a.fd_out = check_fileno(io_out);
166 bytes = (ssize_t)io_run(nogvl_splice, &a);
167 if (bytes == -1) {
168 if (errno == EINTR)
169 continue;
170 if (waitall && errno == EAGAIN) {
171 rb_io_wait_readable(check_fileno(io_in));
172 errno = EAGAIN;
173 rb_io_wait_writable(check_fileno(io_out));
174 continue;
176 if (total > 0)
177 return total;
178 return bytes;
179 } else if (bytes == 0) {
180 break;
181 } else if (waitall) {
182 total += bytes;
183 if ((a.len -= bytes) == 0)
184 return total;
185 i += bytes;
186 o += bytes;
187 } else {
188 return bytes;
192 return total;
196 * call-seq:
197 * IO.splice(io_in, off_in, io_out, off_out, len) => integer
198 * IO.splice(io_in, off_in, io_out, off_out, len, flags) => integer
200 * Splice +len+ bytes from/to a pipe. Either +io_in+ or +io_out+
201 * MUST be a pipe. +io_in+ and +io_out+ may BOTH be pipes as of
202 * Linux 2.6.31 or later.
204 * +off_in+ and +off_out+ if non-nil may be used to
205 * specify an offset for the non-pipe file descriptor.
207 * +flags+ defaults to zero if unspecified.
208 * +flags+ may be a bitmask of the following flags:
210 * * IO::Splice::F_MOVE
211 * * IO::Splice::F_NONBLOCK
212 * * IO::Splice::F_MORE
213 * * IO::Splice::WAITALL
215 * Returns the number of bytes spliced.
216 * Raises EOFError when +io_in+ has reached end of file.
217 * Raises Errno::EAGAIN if the IO::Splice::F_NONBLOCK flag is set
218 * and the pipe has no data to read from or space to write to. May
219 * also raise Errno::EAGAIN if the non-pipe descriptor has no data
220 * to read from or space to write to.
222 * As splice never exposes buffers to userspace, it will not take
223 * into account userspace buffering done by Ruby or stdio. It is
224 * also not subject to encoding/decoding filters under Ruby 1.9.
226 * Consider using IO.trysplice if +io_out+ is a pipe or if you are using
227 * non-blocking I/O on both descriptors as it avoids the cost of raising
228 * common Errno::EAGAIN exceptions.
230 * See manpage for full documentation:
231 * http://kernel.org/doc/man-pages/online/pages/man2/splice.2.html
233 static VALUE my_splice(int argc, VALUE *argv, VALUE self)
235 ssize_t n = do_splice(argc, argv, 0);
237 if (n == 0)
238 rb_eof_error();
239 if (n == -1)
240 rb_sys_fail("splice");
241 return SSIZET2NUM(n);
245 * call-seq:
246 * IO.trysplice(io_in, off_in, io_out, off_out, len) => integer
247 * IO.trysplice(io_in, off_in, io_out, off_out, len, flags) => integer
249 * Exactly like IO.splice, except +:EAGAIN+ is returned when either
250 * the read or write end would block instead of raising Errno::EAGAIN.
252 * IO::Splice::F_NONBLOCK is always passed for the pipe descriptor,
253 * but this can still block if the non-pipe descriptor is blocking.
255 * See IO.splice documentation for more details.
257 * This method is recommended whenever +io_out+ is a pipe.
259 static VALUE trysplice(int argc, VALUE *argv, VALUE self)
261 ssize_t n = do_splice(argc, argv, SPLICE_F_NONBLOCK);
263 if (n == 0)
264 return Qnil;
265 if (n == -1) {
266 if (errno == EAGAIN)
267 return sym_EAGAIN;
268 rb_sys_fail("splice");
270 return SSIZET2NUM(n);
273 struct tee_args {
274 int fd_in;
275 int fd_out;
276 size_t len;
277 unsigned flags;
280 /* runs without GVL */
281 static VALUE nogvl_tee(void *ptr)
283 struct tee_args *a = ptr;
285 if (a->len > MAX_AT_ONCE)
286 a->len = MAX_AT_ONCE;
288 return (VALUE)tee(a->fd_in, a->fd_out, a->len, a->flags);
291 static ssize_t do_tee(int argc, VALUE *argv, unsigned dflags)
293 VALUE io_in, io_out, len, flags;
294 struct tee_args a;
295 ssize_t bytes;
296 ssize_t total = 0;
297 unsigned waitall;
299 rb_scan_args(argc, argv, "31", &io_in, &io_out, &len, &flags);
300 a.len = (size_t)NUM2SIZET(len);
301 a.flags = NIL_P(flags) ? dflags : NUM2UINT(flags) | dflags;
302 waitall = a.flags & WAITALL;
303 if (waitall)
304 a.flags ^= WAITALL;
306 for (;;) {
307 a.fd_in = check_fileno(io_in);
308 a.fd_out = check_fileno(io_out);
309 bytes = (ssize_t)io_run(nogvl_tee, &a);
310 if (bytes == -1) {
311 if (errno == EINTR)
312 continue;
313 if (waitall && errno == EAGAIN) {
314 rb_io_wait_readable(check_fileno(io_in));
315 errno = EAGAIN;
316 rb_io_wait_writable(check_fileno(io_out));
317 continue;
319 if (total > 0)
320 return total;
321 return bytes;
322 } else if (bytes == 0) {
323 break;
324 } else if (waitall) {
325 total += bytes;
326 if ((a.len -= bytes) == 0)
327 return total;
328 } else {
329 return bytes;
333 return total;
337 * call-seq:
338 * IO.tee(io_in, io_out, len) => integer
339 * IO.tee(io_in, io_out, len, flags) => integer
341 * Copies up to +len+ bytes of data from +io_in+ to +io_out+. +io_in+
342 * and +io_out+ must both refer to pipe descriptors. +io_in+ and +io_out+
343 * may not be endpoints of the same pipe.
345 * +flags+ may be zero (the default) or a combination of:
346 * * IO::Splice::F_NONBLOCK
347 * * IO::Splice::WAITALL
349 * Other IO::Splice flags are currently unimplemented or have no effect.
351 * Returns the number of bytes duplicated if successful.
352 * Raises EOFError when +io_in+ is closed and emptied.
353 * Raises Errno::EAGAIN when +io_in+ is empty and/or +io_out+ is full
354 * and +flags+ contains IO::Splice::F_NONBLOCK
356 * Consider using IO.trytee if you are using IO::Splice::F_NONBLOCK
357 * as it avoids the cost of raising common Errno::EAGAIN exceptions.
359 * See manpage for full documentation:
360 * http://kernel.org/doc/man-pages/online/pages/man2/tee.2.html
362 static VALUE my_tee(int argc, VALUE *argv, VALUE self)
364 ssize_t n = do_tee(argc, argv, 0);
366 if (n == 0)
367 rb_eof_error();
368 if (n == -1)
369 rb_sys_fail("tee");
371 return SSIZET2NUM(n);
375 * call-seq:
376 * IO.trytee(io_in, io_out, len) => integer
377 * IO.trytee(io_in, io_out, len, flags) => integer
379 * Exactly like IO.tee, except +:EAGAIN+ is returned when either
380 * the read or write end would block instead of raising Errno::EAGAIN.
382 * IO::Splice::F_NONBLOCK is always passed for the pipe descriptor,
383 * but this can still block if the non-pipe descriptor is blocking.
385 * See IO.tee documentation for more details.
387 static VALUE trytee(int argc, VALUE *argv, VALUE self)
389 ssize_t n = do_tee(argc, argv, SPLICE_F_NONBLOCK);
391 if (n == 0)
392 return Qnil;
393 if (n == -1) {
394 if (errno == EAGAIN)
395 return sym_EAGAIN;
396 rb_sys_fail("tee");
399 return SSIZET2NUM(n);
402 struct vmsplice_args {
403 int fd;
404 struct iovec *iov;
405 unsigned long nr_segs;
406 unsigned flags;
409 static VALUE nogvl_vmsplice(void *ptr)
411 struct vmsplice_args *a = ptr;
413 return (VALUE)vmsplice(a->fd, a->iov, a->nr_segs, a->flags);
416 /* this can't be a function since we use alloca() */
417 #define ARY2IOVEC(iov,iovcnt,expect,ary) \
418 do { \
419 VALUE *cur; \
420 struct iovec *tmp; \
421 long n; \
422 cur = RARRAY_PTR(ary); \
423 n = RARRAY_LEN(ary); \
424 if (n > IOV_MAX) \
425 rb_raise(rb_eArgError, "array is larger than IOV_MAX"); \
426 iov = tmp = alloca(sizeof(struct iovec) * n); \
427 expect = 0; \
428 iovcnt = n; \
429 for (; --n >= 0; tmp++, cur++) { \
430 Check_Type(*cur, T_STRING); \
431 tmp->iov_base = RSTRING_PTR(*cur); \
432 tmp->iov_len = RSTRING_LEN(*cur); \
433 expect += tmp->iov_len; \
435 } while (0)
437 static void advance_vmsplice_args(struct vmsplice_args *a, long n)
439 struct iovec *new_iov = a->iov;
440 unsigned long i;
442 /* skip over iovecs we've already written completely */
443 for (i = 0; i < a->nr_segs; i++, new_iov++) {
444 if (n == 0)
445 break;
447 * partially written iov,
448 * modify and retry with current iovec in
449 * front
451 if (new_iov->iov_len > (size_t)n) {
452 VALUE base = (VALUE)new_iov->iov_base;
454 new_iov->iov_len -= n;
455 new_iov->iov_base = (void *)(base + n);
456 break;
459 n -= new_iov->iov_len;
462 /* setup to retry without the already-written iovecs */
463 a->nr_segs -= i;
464 a->iov = new_iov;
468 * call-seq:
469 * IO.vmsplice(io, string_array) => integer
470 * IO.vmsplice(io, string_array, flags) => integer
471 * IO.vmsplice(io, string) => integer
472 * IO.vmsplice(io, string, flags) => integer
474 * Transfers an array of strings into the pipe descriptor given by io.
475 * +io+ must be the writable end of a pipe.
477 * This may allow the kernel to avoid data copies in some cases.
478 * but is (probably) of limited usefulness in Ruby. If you have
479 * use cases or ideas for making this more useful for Ruby users,
480 * please tell us at ruby.io.splice@librelist.org!
482 * Also consider the "sendfile" RubyGem or IO.copy_stream in Ruby 1.9
483 * if you want to do zero-copy file transfers to pipes or sockets. As
484 * of Linux 2.6.33, sendfile(2) can copy to any output descriptor,
485 * not just sockets.
487 * See manpage for full documentation:
488 * http://kernel.org/doc/man-pages/online/pages/man2/vmsplice.2.html
490 static VALUE my_vmsplice(int argc, VALUE * argv, VALUE self)
492 ssize_t rv = 0;
493 ssize_t left;
494 struct vmsplice_args a;
495 struct iovec iov;
496 ssize_t n;
498 VALUE io, data, flags;
500 rb_scan_args(argc, argv, "21", &io, &data, &flags);
502 switch (TYPE(data)) {
503 case T_STRING:
504 iov.iov_base = RSTRING_PTR(data);
505 iov.iov_len = (size_t)(left = (ssize_t)RSTRING_LEN(data));
506 a.iov = &iov;
507 a.nr_segs = 1;
508 break;
509 case T_ARRAY:
510 ARY2IOVEC(a.iov, a.nr_segs, left, data);
511 break;
512 default:
513 rb_raise(rb_eTypeError, "wrong argument type %s "
514 "(expected a String or Array of strings)",
515 rb_obj_classname(data));
518 a.flags = NIL_P(flags) ? 0 : NUM2UINT(flags);
520 for (;;) {
521 a.fd = check_fileno(io);
522 n = (ssize_t)io_run(nogvl_vmsplice, &a);
524 if (n == -1) {
525 if (errno == EAGAIN) {
526 if (a.flags & SPLICE_F_NONBLOCK)
527 rb_sys_fail("vmsplice");
528 if (rb_io_wait_writable(check_fileno(io)))
529 continue;
530 /* fall through on error */
533 * unlikely to hit this case, return the
534 * already written bytes, we'll let the next
535 * write (or close) fail instead
537 if (rv > 0)
538 break;
539 if (errno == EINTR)
540 continue;
541 rb_sys_fail("vmsplice");
544 rv += n;
545 left -= n;
546 if (left == 0)
547 break;
548 advance_vmsplice_args(&a, n);
551 return SSIZET2NUM(rv);
555 * call-seq:
556 * reader, writer = IO.pipe
557 * reader.pipe_size => integer
559 * Returns the pipe capacity of the underlying pipe in bytes. The
560 * default capacity is 65536 bytes since Linux 2.6.11, and 4096 bytes
561 * in previous kernels.
563 * Since the pipe is a circular buffer in the same kernel, the size
564 * of the reader is exactly the same as the size of the writer.
566 * This method is only exposed on Linux 2.6.35 or later.
568 static VALUE pipe_size(VALUE self)
570 int size = fcntl(my_fileno(self), F_GETPIPE_SZ);
572 if (size < 0)
573 rb_sys_fail("fcntl(F_GETPIPE_SZ)");
575 return INT2NUM(size);
579 * call-seq:
580 * reader, writer = IO.pipe
581 * reader.pipe_size = integer
583 * Sets and returns the pipe capacity of the underlying pipe in bytes.
585 * This MUST be a power-of-two, or Errno::EINVAL will be raised.
586 * Linux will silently increase this to be equal to the page size
587 * (4096 bytes on most architectures) if the specified value is
588 * less than the size of a page.
590 * For users without CAP_SYS_RESOURCE, this raises Errno::EPERM when
591 * attempting to specify a value greater than the value in
592 * /proc/sys/fs/pipe-max-size.
594 * Since the pipe is a circular buffer in the same kernel, the size
595 * of the reader is exactly the same as the size of the writer.
597 * Raises Errno::EBUSY if the assigned value is less than
598 * the currently filled portion of the pipe.
600 * This method is only exposed on Linux 2.6.35 or later.
602 static VALUE set_pipe_size(VALUE self, VALUE size)
604 int fd = my_fileno(self);
605 int bytes = NUM2INT(size);
606 int rv = fcntl(fd, F_SETPIPE_SZ, bytes);
608 if (rv < 0) {
609 if (errno == ENOMEM) {
610 rb_gc();
611 rv = fcntl(fd, F_SETPIPE_SZ, bytes);
613 if (rv < 0)
614 rb_sys_fail("fcntl(F_SETPIPE_SZ)");
617 return size;
620 static int can_mod_pipe_size(void)
623 * pipe2 appeared in Linux 2.6.27, F_*PIPE_SZ appeared in 2.6.35,
624 * thus not having pipe2 automatically disqualifies us from having
625 * F_*PIPE_SZ support
627 #ifdef HAVE_PIPE2
628 int fds[2];
629 int rc = pipe2(fds, O_CLOEXEC);
631 if (rc == 0) {
632 rc = fcntl(fds[0], F_GETPIPE_SZ);
633 rc = rc < 0 ? 0 : 1;
635 (void)close(fds[0]);
636 (void)close(fds[1]);
637 } else {
639 * weird error, but don't raise during init, this could be
640 * ENOSYS, even..
642 rc = 0;
644 errno = 0;
645 return rc;
646 #else /* ! HAVE_PIPE2 */
647 return 0;
648 #endif /* ! HAVE_PIPE2 */
651 void Init_io_splice_ext(void)
653 VALUE mSplice = rb_define_module_under(rb_cIO, "Splice");
655 rb_define_singleton_method(rb_cIO, "splice", my_splice, -1);
656 rb_define_singleton_method(rb_cIO, "trysplice", trysplice, -1);
657 rb_define_singleton_method(rb_cIO, "tee", my_tee, -1);
658 rb_define_singleton_method(rb_cIO, "trytee", trytee, -1);
659 rb_define_singleton_method(rb_cIO, "vmsplice", my_vmsplice, -1);
662 * Attempt to move pages instead of copying. This is only a hint
663 * and support for it was removed in Linux 2.6.21. It will be
664 * re-added for FUSE filesystems only in Linux 2.6.35.
666 rb_define_const(mSplice, "F_MOVE", UINT2NUM(SPLICE_F_MOVE));
667 assert(WAITALL != SPLICE_F_MOVE && "WAITALL == F_MOVE");
670 * Do not block on pipe I/O. This flag only affects the pipe(s)
671 * being spliced from/to and has no effect on the non-pipe
672 * descriptor (which requires non-blocking operation to be set
673 * explicitly).
675 * The non-blocking flag (O_NONBLOCK) on the pipe descriptors
676 * themselves are ignored by this family of functions, and
677 * using this flag is the only way to get non-blocking operation
678 * out of them.
680 * It is highly recommended this flag be set (or IO.trysplice used)
681 * whenever splicing from a socket into a pipe unless there is
682 * another (native) thread or process doing a blocking read on that
683 * pipe. Otherwise it is possible to block a single-threaded process
684 * if the socket buffers are larger than the pipe buffers.
686 rb_define_const(mSplice, "F_NONBLOCK", UINT2NUM(SPLICE_F_NONBLOCK));
687 assert(WAITALL != SPLICE_F_NONBLOCK && "WAITALL == F_NONBLOCK");
690 * Indicate that there may be more data coming into the outbound
691 * descriptor. This can allow the kernel to avoid sending partial
692 * frames from sockets. Currently only used with splice.
694 rb_define_const(mSplice, "F_MORE", UINT2NUM(SPLICE_F_MORE));
695 assert(WAITALL != SPLICE_F_MORE && "WAITALL == F_MORE");
698 * Only usable by vmsplice. This flag probably not useful in the
699 * context of Ruby applications which cannot control alignment.
701 rb_define_const(mSplice, "F_GIFT", UINT2NUM(SPLICE_F_GIFT));
702 assert(WAITALL != SPLICE_F_GIFT && "WAITALL == F_GIFT");
705 * Retry until the requested transfer is complete, this will
706 * cause IO.splice/IO.tee to never return less than the requested
707 * transfer size unless an error occored.
709 * IO.vmsplice always defaults to this behavior.
711 rb_define_const(mSplice, "WAITALL", UINT2NUM(WAITALL));
714 * The maximum size of an atomic write to a pipe
715 * POSIX requires this to be at least 512 bytes.
716 * Under Linux, this is 4096 bytes.
718 rb_define_const(mSplice, "PIPE_BUF", UINT2NUM(PIPE_BUF));
721 * The maximum size we're allowed to splice at once. Larger
722 * sizes will be broken up and retried if the WAITALL flag or
723 * IO::Splice.copy_stream is used.
725 rb_define_const(mSplice, "MAX_AT_ONCE", SIZET2NUM(MAX_AT_ONCE));
727 if (can_mod_pipe_size()) {
728 rb_define_method(rb_cIO, "pipe_size", pipe_size, 0);
729 rb_define_method(rb_cIO, "pipe_size=", set_pipe_size, 1);
732 * fcntl() command constant used to return the size of a pipe.
733 * This constant is only defined when running Linux 2.6.35
734 * or later. For convenience, use IO#pipe_size instead.
736 rb_define_const(mSplice, "F_GETPIPE_SZ",
737 UINT2NUM(F_GETPIPE_SZ));
740 * fcntl() command constant used to set the size of a pipe.
741 * This constant is only defined when running Linux 2.6.35
742 * or later. For convenience, use IO#pipe_size= instead.
744 rb_define_const(mSplice, "F_SETPIPE_SZ",
745 UINT2NUM(F_SETPIPE_SZ));
748 sym_EAGAIN = ID2SYM(rb_intern("EAGAIN"));