Method: IO.pipe

Defined in:
io.c

.pipe(**opts) ⇒ Array .pipe(enc, **opts) ⇒ Array .pipe(ext_enc, int_enc, **opts) ⇒ Array .pipe(**opts) {|read_io, write_io| ... } ⇒ Object .pipe(enc, **opts) {|read_io, write_io| ... } ⇒ Object .pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ... } ⇒ Object

Creates a pair of pipe endpoints, read_io and write_io, connected to each other.

If argument enc_string is given, it must be a string containing one of:

  • The name of the encoding to be used as the external encoding.

  • The colon-separated names of two encodings to be used as the external and internal encodings.

If argument int_enc is given, it must be an Encoding object or encoding name string that specifies the internal encoding to be used; if argument ext_enc is also given, it must be an Encoding object or encoding name string that specifies the external encoding to be used.

The string read from read_io is tagged with the external encoding; if an internal encoding is also specified, the string is converted to, and tagged with, that encoding.

If any encoding is specified, optional hash arguments specify the conversion option.

Optional keyword arguments opts specify:

With no block given, returns the two endpoints in an array:

IO.pipe # => [#<IO:fd 4>, #<IO:fd 5>]

With a block given, calls the block with the two endpoints; closes both endpoints and returns the value of the block:

IO.pipe {|read_io, write_io| p read_io; p write_io }

Output:

#<IO:fd 6>
#<IO:fd 7>

Not available on all platforms.

In the example below, the two processes close the ends of the pipe that they are not using. This is not just a cosmetic nicety. The read end of a pipe will not generate an end of file condition if there are any writers with the pipe still open. In the case of the parent process, the rd.read will never return if it does not first issue a wr.close:

rd, wr = IO.pipe

if fork
  wr.close
  puts "Parent got: <#{rd.read}>"
  rd.close
  Process.wait
else
  rd.close
  puts 'Sending message to parent'
  wr.write "Hi Dad"
  wr.close
end

produces:

Sending message to parent
Parent got: <Hi Dad>

Overloads:

  • .pipe(**opts) ⇒ Array

    Returns:

  • .pipe(enc, **opts) ⇒ Array

    Returns:

  • .pipe(ext_enc, int_enc, **opts) ⇒ Array

    Returns:

  • .pipe(**opts) {|read_io, write_io| ... } ⇒ Object

    Yields:

    • (read_io, write_io)

    Returns:

  • .pipe(enc, **opts) {|read_io, write_io| ... } ⇒ Object

    Yields:

    • (read_io, write_io)

    Returns:

  • .pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ... } ⇒ Object

    Yields:

    • (read_io, write_io)

    Returns:



11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
# File 'io.c', line 11870

static VALUE
rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
{
    int pipes[2], state;
    VALUE r, w, args[3], v1, v2;
    VALUE opt;
    rb_io_t *fptr, *fptr2;
    struct io_encoding_set_args ies_args;
    int fmode = 0;
    VALUE ret;

    argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
    if (rb_pipe(pipes) < 0)
        rb_sys_fail(0);

    args[0] = klass;
    args[1] = INT2NUM(pipes[0]);
    args[2] = INT2FIX(O_RDONLY);
    r = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[0]);
        close(pipes[1]);
        rb_jump_tag(state);
    }
    GetOpenFile(r, fptr);

    ies_args.fptr = fptr;
    ies_args.v1 = v1;
    ies_args.v2 = v2;
    ies_args.opt = opt;
    rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
    if (state) {
        close(pipes[1]);
        io_close(r);
        rb_jump_tag(state);
    }

    args[1] = INT2NUM(pipes[1]);
    args[2] = INT2FIX(O_WRONLY);
    w = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[1]);
        if (!NIL_P(r)) rb_io_close(r);
        rb_jump_tag(state);
    }
    GetOpenFile(w, fptr2);
    rb_io_synchronized(fptr2);

    extract_binmode(opt, &fmode);

    if ((fmode & FMODE_BINMODE) && NIL_P(v1)) {
        rb_io_ascii8bit_binmode(r);
        rb_io_ascii8bit_binmode(w);
    }

#if DEFAULT_TEXTMODE
    if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr->mode &= ~FMODE_TEXTMODE;
        setmode(fptr->fd, O_BINARY);
    }
#if RUBY_CRLF_ENVIRONMENT
    if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
        fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
    }
#endif
#endif
    fptr->mode |= fmode;
#if DEFAULT_TEXTMODE
    if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr2->mode &= ~FMODE_TEXTMODE;
        setmode(fptr2->fd, O_BINARY);
    }
#endif
    fptr2->mode |= fmode;

    ret = rb_assoc_new(r, w);
    if (rb_block_given_p()) {
        VALUE rw[2];
        rw[0] = r;
        rw[1] = w;
        return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
    }
    return ret;
}