[Win32utils-devel] IO.socketpair addition -- very helpful!

Daniel Berger djberg96 at gmail.com
Thu Mar 27 19:03:07 EDT 2008


Steve,

Thanks for this.

May I recommend joining the win32utils-devel mailing list? You would
be most welcome with ideas like this!

Regards,

Dan

On Thu, Mar 27, 2008 at 9:52 AM, Steve Shreeve <steve.shreeve at gmail.com> wrote:
>
>
> Dan,
>
> I had nearly pulled my hair out over the past week trying to figure out why
> I couldn't spawn a process on Windows and communicate with it. A few things
> I found out later:
>
> 1) The 'fork' implementation is totally gorked and should be renamed to
> something other that 'fork'... it's more like 'clone_me_and_do_over()'.
> 2) On Windows, pipes are essentially worthless because select() always says
> there's data, which will take you into a black hole if you try to read it.
>
> I *did* figure out, however, that sockets actually behave quite nicely on
> Windows. Also, I found your latest win32/process has some nice additions
> (modulo the few tweakers we've been discussing recently).
>
> In order to create a fairly clean way to interact with subprocesses, I've
> now got the code below.
>
> Let me know if this is helpful.
>
> Thanks,
>
> Steve
>
> ==
>
> require 'socket'
>
> STDIN.sync = STDOUT.sync = STDERR.sync = true
>
> class IO
>   def self.socketpair(sync=true)
>     if RUBY_PLATFORM.include?('win32')
>       tcp = TCPServer.new('127.0.0.1', 0)
>       one = TCPSocket.new('127.0.0.1', tcp.addr[1])
>       two = tcp.accept and tcp.close
>     else
>       one, two = UNIXSocket.socketpair
>     end
>     one.sync = two.sync = true if sync
>     [one, two]
>   end
>
>   def self.spawn(cmd=nil)
>     io, child_io = IO.socketpair
>
>     require 'win32/process'
>     child = Process.create(
>       'app_name' => "cmd /k #{cmd}", # the "/k" keeps the process around
> when it's done
>       'process_inherit' => true, # not yet sure if this one is actually
> needed
>       'thread_inherit' => true, # not yet sure if this one is actually
> needed
>       'startup_info' => {
>         'stdin'  => child_io,
>         'stdout' => child_io,
>         'stderr' => File.open('nul', 'wb') # ignore STDERR, for now (what
> about sync? close?)
>       }
>     )
>     at_exit do
>       Process.TerminateProcess(child.process_handle, child.process_id)
>       Process.CloseHandle(child.process_handle)
>     end
>     child_io.close
>
>     io
>   end
> end
>
> io = IO.spawn('date')
>
> # communicate using "io" and control threads...
>


More information about the win32utils-devel mailing list