# Arbitrary IO object

**URL:** <https://www.ruby-forum.com/t/arbitrary-io-object/138164>\
**Category:** Ruby\
**Created:** [May 20, 2008, 6:40pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164 "2008-05-20T18:40:59Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [May 20, 2008, 6:40pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164/1 "2008-05-20T18:40:59Z")

</div>

Hi,

How would I go about using IO.new such that it would automatically  
grab the next available file descriptor? I don’t know the fileno in  
advance and I can’t use StringIO.

What are my options?

Thanks,

Dan

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [May 20, 2008, 7:25pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164/2 "2008-05-20T19:25:50Z")

</div>

On 20.05.2008 18:40, Daniel B. wrote:

> How would I go about using IO.new such that it would automatically  
> grab the next available file descriptor?

Not sure what you mean: File.open uses a new file descriptor. Why would  
you care about the file descriptor numbering?

> I don’t know the fileno in  
> advance and I can’t use StringIO.

Why would you want to use StringIO to read from files?

> What are my options?

What are you trying to achieve?

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [May 20, 2008, 7:34pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164/3 "2008-05-20T19:34:38Z")

</div>

On May 20, 11:25 am, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Why would you want to use StringIO to read from files?
> 
> > What are my options?
> 
> What are you trying to achieve?

I’m tinkering with possibly reimplementing win32-open3 using the win32-  
process library. You can redirect stdin, stdout and stderr like so:

info = Process.create(  
input = IO.new(x, ‘w+’) # Want next available fd  
output = IO.new(y, ‘w+’) # Want next available fd  
error = IO.new(z, ‘w+’) # Want next available fd

:app\_name =\> command,  
:creation\_flags =\> Process::DETACHED\_PROCESS,  
:startup\_info =\> {  
:stdin =\> input,  
:stdout =\> output,  
:stderr =\> error  
}  
)

pid = info.process\_id

return [input, output, error, pid]

That’s the general idea, anyway.

Regards,

Dan

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [May 20, 2008, 9:28pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164/4 "2008-05-20T21:28:03Z")

</div>

On May 20, 12:36 pm, Gary W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > :creation\_flags =\> Process::DETACHED\_PROCESS,  
> > mechanism in order to be useful via IO.new. You can  
> > use IO#fileno to discover the underlying OS file  
> > descriptor from a Ruby object but if you’ve already  
> > got a Ruby IO object you don’t need to use IO.new.
> 
> At the C/POSIX level I don’t think there is really  
> any concept of specifying the ‘next available fd’.  
> You just call open/create/pipe/dup and use the integer  
> file descriptors that are returned. The OS figures  
> out which integer descriptors are available.

Yep, looks like I should just use IO.pipe.

Thanks,

Dan

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [May 20, 2008, 8:37pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164/5 "2008-05-20T20:37:47Z")

</div>

On May 20, 2008, at 1:34 PM, Daniel B. wrote:

> ```
> :stdout => output,
> :stderr => error
> 
> ```
> 
> }  
> )

IO.new is for associating a Ruby IO object with  
an already open OS file descriptor. So you’ve got  
to acquire the file descriptor through some non-Ruby  
mechanism in order to be useful via IO.new. You can  
use IO#fileno to discover the underlying OS file  
descriptor from a Ruby object but if you’ve already  
got a Ruby IO object you don’t need to use IO.new.

At the C/POSIX level I don’t think there is really  
any concept of specifying the ‘next available fd’.  
You just call open/create/pipe/dup and use the integer  
file descriptors that are returned. The OS figures  
out which integer descriptors are available.

Gary W.

---

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [May 20, 2008, 11:35pm UTC](https://www.ruby-forum.com/t/arbitrary-io-object/138164/6 "2008-05-20T23:35:59Z")

</div>

On 20.05.2008 19:34, Daniel B. wrote:

> > > advance and I can’t use StringIO.  
> > > output = IO.new(y, ‘w+’) # Want next available fd  
> > > error = IO.new(z, ‘w+’) # Want next available fd

It does not seem to make sense to open all these both for reading and  
writing.

> :app\_name =\> command,  
> :creation\_flags =\> Process::DETACHED\_PROCESS,  
> :startup\_info =\> {  
> :stdin =\> input,  
> :stdout =\> output,  
> :stderr =\> error  
> }  
> )

Not sure what this is supposed to do - this isn’t even valid Ruby as far  
as I can see:

$ ruby -c \<\<EOF

> info = Process.create(  
> input = IO.new(x, ‘w+’) # Want next available fd  
> output = IO.new(y, ‘w+’) # Want next available fd  
> error = IO.new(z, ‘w+’) # Want next available fd
> 
> :app\_name =\> command,  
> :creation\_flags =\> Process::DETACHED\_PROCESS,  
> :startup\_info =\> {  
> :stdin =\> input,  
> :stdout =\> output,  
> :stderr =\> error  
> }  
> )  
> EOF  
> -:3: syntax error, unexpected tIDENTIFIER, expecting ‘)’  
> output = IO.new(y, ‘w+’) # Want next available fd  
> ^  
> -:6: syntax error, unexpected tASSOC, expecting $end  
> :app\_name =\> command,  
> ^

$

> pid = info.process\_id
> 
> return [input, output, error, pid]
> 
> That’s the general idea, anyway.

You only have two options:

- you overlay a process, then it makes sense that the new process  
inherits all standard file descriptors (0,1,2 - stdin, stdout, stderr).  
Usually nothing needs to be done for this (at least on POSIX systems)

- you copy the process (fork on POSIX) and want to be in control of the  
child’ IO, in that case you need to establish pipes to feed stdin and  
read from stdout and stderr.

Kind regards

robert
