sockets, windoze, and threads

A

ara howard

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/
 
G

Gordon Thiesfeld

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
 
L

Luis Lavena

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')

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/


Will test it later and get back to you ;-)
 
A

ara.t.howard

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

??

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/
 
J

James Tucker

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.
has_fork = fork{ exit! } rescue nil

??

this is really great - my thoughts on the topic are well documented
in the archives ;-)
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...

It may be possible to use named pipes?

I will test this when I get to the office,

same to you :)

james / raggi.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top