lib/systemu.rb in systemu-1.1.0 vs lib/systemu.rb in systemu-1.2.0
- old
+ new
@@ -1,5 +1,6 @@
+# vim: ts=2:sw=2:sts=2:et:fdm=marker
require 'tmpdir'
require 'socket'
require 'fileutils'
require 'rbconfig'
require 'thread'
@@ -8,16 +9,15 @@
class Object
def systemu(*a, &b) SystemUniversal.new(*a, &b).systemu end
end
class SystemUniversal
-#--{{{
#
# constants
#
- SystemUniversal::VERSION = '1.1.0' unless defined? SystemUniversal::VERSION
- def version() VERSION end
+ SystemUniversal::VERSION = '1.2.0' unless defined? SystemUniversal::VERSION
+ def version() SystemUniversal::VERSION end
#
# class methods
#
@host = Socket.gethostname
@@ -40,11 +40,10 @@
#
# instance methods
#
def initialize argv, opts = {}, &block
-#--{{{
getopt = getopts opts
@argv = argv
@block = block
@@ -56,25 +55,20 @@
@host = getopt[ 'host', self.class.host ]
@ppid = getopt[ 'ppid', self.class.ppid ]
@pid = getopt[ 'pid', self.class.pid ]
@ruby = getopt[ 'ruby', self.class.ruby ]
-#--}}}
end
def systemu
-#--{{{
tmpdir do |tmp|
c = child_setup tmp
status = nil
- if @block
- q = Queue.new
- t = Thread.new{ Thread.current_abort_on_exception = true; @block[ q.pop ] }
- end
-
begin
+ thread = nil
+
quietly{
IO.popen "#{ @ruby } #{ c['program'] }", 'r+' do |pipe|
line = pipe.gets
case line
when %r/^pid: \d+$/
@@ -88,33 +82,50 @@
raise e
rescue
raise "wtf?\n#{ buf }\n"
end
end
- cid = Integer pipe.gets
- q.push cid if @block
+ thread = new_thread cid, @block if @block
pipe.read rescue nil
end
}
status = $?
ensure
- t.kill rescue nil if t
+ if thread
+ begin
+ class << status
+ attr 'thread'
+ end
+ status.instance_eval{ @thread = thread }
+ rescue
+ 42
+ end
+ end
end
if @stdout or @stderr
open(c['stdout']){|f| relay f => @stdout} if @stdout
open(c['stderr']){|f| relay f => @stderr} if @stderr
status
else
[status, IO.read(c['stdout']), IO.read(c['stderr'])]
end
end
-#--}}}
end
+ def new_thread cid, block
+ q = Queue.new
+ Thread.new(cid) do |cid|
+ current = Thread.current
+ current.abort_on_exception = true
+ q.push current
+ block.call cid
+ end
+ q.pop
+ end
+
def child_setup tmp
-#--{{{
stdin = File.expand_path(File.join(tmp, 'stdin'))
stdout = File.expand_path(File.join(tmp, 'stdout'))
stderr = File.expand_path(File.join(tmp, 'stderr'))
program = File.expand_path(File.join(tmp, 'program'))
config = File.expand_path(File.join(tmp, 'config'))
@@ -138,25 +149,21 @@
open(config, 'w'){|f| YAML.dump c, f}
open(program, 'w'){|f| f.write child_program(config)}
c
-#--}}}
end
def quietly
-#--{{{
v = $VERBOSE
$VERBOSE = nil
yield
ensure
$VERBOSE = v
-#--}}}
end
def child_program config
-#--{{{
<<-program
PIPE = STDOUT.dup
begin
require 'yaml'
@@ -174,36 +181,32 @@
STDIN.reopen stdin
STDOUT.reopen stdout
STDERR.reopen stderr
- PIPE.puts "pid: #{ Process.pid }"
+ PIPE.puts "pid: \#{ Process.pid }"
PIPE.flush ### the process is ready yo!
PIPE.close
exec *argv
rescue Exception => e
PIPE.write Marshal.dump(e) rescue nil
exit 42
end
program
-#--}}}
end
def relay srcdst
-#--{{{
src, dst, ignored = srcdst.to_a.first
if src.respond_to? 'read'
while((buf = src.read(8192))); dst << buf; end
else
src.each{|buf| dst << buf}
end
-#--}}}
end
def tmpdir d = Dir.tmpdir, max = 42, &b
-#--{{{
i = -1 and loop{
i += 1
tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"
@@ -224,15 +227,13 @@
else
tmp
end
)
}
-#--}}}
end
def getopts opts = {}
-#--{{{
lambda do |*args|
keys, default, ignored = args
catch('opt') do
[keys].flatten.each do |key|
[key, key.to_s, key.to_s.intern].each do |key|
@@ -240,15 +241,24 @@
end
end
default
end
end
-#--}}}
end
-#--}}}
end
SystemU = SystemUniversal unless defined? SystemU
+
+
+
+
+
+
+
+
+
+
+
if $0 == __FILE__
#
# date