# Sockets, windoze, and threads

**URL:** <https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450>\
**Category:** Ruby\
**Created:** [March 31, 2008, 7:00pm UTC](https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450 "2008-03-31T19:00:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 31, 2008, 7:00pm UTC](https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450/1 "2008-03-31T19:00:36Z")

</div>

this works on \*nix and might on windoze - i don’t have a box near so  
cannot test… can someone give it a whirl and/or patch it to work?  
it should simply run forever:

require ‘socket’

STDIN.sync = STDOUT.sync = STDERR.sync = true

class IO

windoze = RUBY\_PLATFORM.include?(‘win32’)

unless windoze

def IO.socketpair(sync=true)  
one, two = UNIXSocket.socketpair  
one.sync = two.sync = true if sync  
[one, two]  
end

def IO.spawn cmd, options = {}  
stdin = IO.socketpair  
stdout = IO.socketpair  
stderr = IO.socketpair

```
 if cid = fork
   stdin.last.close
   stdout.last.close
   stderr.last.close
 else
   STDIN.reopen stdin.last
   STDOUT.reopen stdout.last
   STDERR.reopen stderr.last
   exec cmd
 end

 at_exit do
   Process.kill(15, cid) rescue nil
   Process.kill(-9, cid) rescue nil
 end

 [cid, stdin.first, stdout.first, stderr.first]

```

end

else

def IO.socketpair(sync=true)  
tcp = TCPServer.new(‘127.0.0.1’, 0)  
one = TCPSocket.new(‘127.0.0.1’, tcp.addr[1])  
two = tcp.accept and tcp.close  
one.sync = two.sync = true if sync  
[one, two]  
end

def IO.spawn cmd, options = {}  
stdin = IO.socketpair  
stdout = IO.socketpair  
stderr = 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’ =\> stdin.last,  
‘stdout’ =\> stdout.last,  
‘stderr’ =\> stderr.last,  
}  
)

```
 at_exit do
   Process.TerminateProcess(child.process_handle,

```

child.process\_id) rescue nil  
Process.CloseHandle(child.process\_handle) rescue nil  
Process.kill(-9, child.process\_id) rescue nil  
end

```
 stdin.last.close
 stdout.last.close
 stderr.last.close

 [child.process_id, stdin.first, stdout.first, stderr.first]

```

end

end

end

# 

# try to clog the pipes

# 

cid, i, o, e = IO.spawn ’ ruby -e"  
loop{ STDOUT.puts(Time.now.to\_f); STDERR.puts(Time.now.to\_f) }" ’

a = Thread.new do  
loop{ STDOUT.puts o.gets }  
end

b = Thread.new do  
loop{ STDOUT.puts e.gets }  
end

sleep

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 31, 2008, 7:39pm UTC](https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450/2 "2008-03-31T19:39:12Z")

</div>

On Mon, Mar 31, 2008 at 11:59 AM, ara howard [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> this works on \*nix and might on windoze - i don’t have a box near so  
> cannot test… can someone give it a whirl and/or patch it to work?  
> it should simply run forever:

It works with win32-process-0.5.7. I tested with 0.5.6 first, and  
there was a bug with the startup\_info hash.

hth,

Gordon

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 31, 2008, 8:51pm UTC](https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450/3 "2008-03-31T20:51:47Z")

</div>

On Mar 31, 1:59 pm, ara howard [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> windoze = RUBY\_PLATFORM.include?(‘win32’)

Ara, didn’t test the code yep, but you should move away from win32 as  
platform matcher for Windows, at least, if you plan your code work  
with the upcoming one-click installer:

[http://blog.mmediasys.com/2008/03/29/progress-of-one-click-installer-rubyinstaller/](http://blog.mmediasys.com/2008/03/29/progress-of-one-click-installer-rubyinstaller/)

Will test it later and get back to you 😉

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [March 31, 2008, 11:07pm UTC](https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450/4 "2008-03-31T23:07:29Z")

</div>

On Mar 31, 2008, at 12:50 PM, Luis L. wrote:

> Ara, didn’t test the code yep, but you should move away from win32 as  
> platform matcher for Windows, at least, if you plan your code work  
> with the upcoming one-click installer:

yeah this is just toy code at this point. still a valid point - what  
would have us do to be rock solid

has\_fork = fork{ exit! } rescue nil

??

> [http://blog.mmediasys.com/2008/03/29/progress-of-one-click-installer-rubyinstaller/](http://blog.mmediasys.com/2008/03/29/progress-of-one-click-installer-rubyinstaller/)

this is really great - my thoughts on the topic are well documented in  
the archives 😉

> Will test it later and get back to you 😉

so far it’s rock solid - what this means is that i’ll be able to  
provide a cross platform open4 impl whereby client code can have  
handles on pid, stdin, stdout, stderr for the child process in a  
_thread safe_ fashion - very cool. the sockets idea is from steve  
shreeve btw…

cheers.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![ara\_howard](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d9b06d/32.png) [@ara\_howard](https://www.ruby-forum.com/u/ara_howard)\
**Post date:** [April 1, 2008, 11:58am UTC](https://www.ruby-forum.com/t/sockets-windoze-and-threads/133450/5 "2008-04-01T11:58:22Z")

</div>

On 31 Mar 2008, at 22:06, ara.t.howard wrote:

> On Mar 31, 2008, at 12:50 PM, Luis L. wrote:
> 
> > Ara, didn’t test the code yep, but you should move away from win32 as  
> > platform matcher for Windows, at least, if you plan your code work  
> > with the upcoming one-click installer:
> 
> yeah this is just toy code at this point. still a valid point -  
> what would have us do to be rock solid

Luis is will know better than I, but these are the two methods I’ve  
been using:

Gem.win\_platform? on RubyGems \> 0.9.5 (or was it .4?)

or

RUBY\_PLATFORM =~ /(cyg|ms)win|mingw/

Although it is worth noting that cygwin acts somewhat like unix  
(although there have been past warnings regarding the lack of security  
inherent in unix sockets under cygwin), so may need tailoring out for  
some platform specific codes.

A more open regex would be:

RUBY\_PLATFORM =~ /win|min/ unless RUBY\_PLATFORM =~ /darwin/

For these purposes, I might be tempted to do something like the  
following (which I know is verbose ☹ )

non\_unix\_platform = Gem.win\_platform? rescue RUBY\_PLATFORM =~ /mswin|  
mingw/

N.B. the rescue covers if rubygems is not loaded, as a fallback.

As you will be able to fork and use unix sockets (for what they’re  
worth) under cygwin.

> handles on pid, stdin, stdout, stderr for the child process in a  
> _thread safe_ fashion - very cool. the sockets idea is from steve  
> shreeve btw…

It may be possible to use named pipes?

I will test this when I get to the office,

> cheers.

same to you 🙂

james / raggi.
