lib/shell/system-command.rb
DEFINITIONS
This source file includes following functions.
1 #
2 # shell/system-command.rb -
3 # $Release Version: 0.6.0 $
4 # $Revision: 1.1 $
5 # $Date: 2001/05/17 10:02:48 $
6 # by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
7 #
8 # --
9 #
10 #
11 #
12
13 require "shell/filter"
14
15 class Shell
16 class SystemCommand < Filter
17 def initialize(sh, command, *opts)
18 if t = opts.find{|opt| !opt.kind_of?(String) && opt.type}
19 Shell.Fail TypeError, t.type, "String"
20 end
21 super(sh)
22 @command = command
23 @opts = opts
24
25 @input_queue = Queue.new
26 @pid = nil
27
28 sh.process_controller.add_schedule(self)
29 end
30
31 attr_reader :command
32 alias name command
33
34 def wait?
35 @shell.process_controller.waiting_job?(self)
36 end
37
38 def active?
39 @shell.process_controller.active_job?(self)
40 end
41
42 def input=(inp)
43 super
44 if active?
45 start_export
46 end
47 end
48
49 def start
50 @pid, @pipe_in, @pipe_out = @shell.process_controller.sfork(self) {
51 Dir.chdir @shell.pwd
52 exec(@command, *@opts)
53 }
54 if @input
55 start_export
56 end
57 start_import
58 end
59
60 def flush
61 @pipe_out.flush if @pipe_out and !@pipe_out.closed?
62 end
63
64 def terminate
65 begin
66 @pipe_in.close
67 rescue IOError
68 end
69 begin
70 @pipe_out.close
71 rescue IOError
72 end
73 end
74
75 def kill(sig)
76 if @pid
77 Process.kill(sig, @pid)
78 end
79 end
80
81
82 def start_import
83 # Thread.critical = true
84 notify "Job(%id) start imp-pipe.", @shell.debug?
85 rs = @shell.record_separator unless rs
86 _eop = true
87 # Thread.critical = false
88 th = Thread.start {
89 Thread.critical = true
90 begin
91 Thread.critical = false
92 while l = @pipe_in.gets
93 @input_queue.push l
94 end
95 _eop = false
96 rescue Errno::EPIPE
97 _eop = false
98 ensure
99 if _eop
100 notify("warn: Process finishing...",
101 "wait for Job[%id] to finish pipe importing.",
102 "You can use Shell#transact or Shell#check_point for more safe execution.")
103 # Tracer.on
104 Thread.current.run
105 redo
106 end
107 Thread.exclusive do
108 notify "job(%id}) close imp-pipe.", @shell.debug?
109 @input_queue.push :EOF
110 @pipe_in.close
111 end
112 end
113 }
114 end
115
116 def start_export
117 notify "job(%id) start exp-pipe.", @shell.debug?
118 _eop = true
119 th = Thread.start{
120 Thread.critical = true
121 begin
122 Thread.critical = false
123 @input.each{|l| @pipe_out.print l}
124 _eop = false
125 rescue Errno::EPIPE
126 _eop = false
127 ensure
128 if _eop
129 notify("shell: warn: Process finishing...",
130 "wait for Job(%id) to finish pipe exporting.",
131 "You can use Shell#transact or Shell#check_point for more safe execution.")
132 # Tracer.on
133 redo
134 end
135 Thread.exclusive do
136 notify "job(%id) close exp-pipe.", @shell.debug?
137 @pipe_out.close
138 end
139 end
140 }
141 end
142
143 alias super_each each
144 def each(rs = nil)
145 while (l = @input_queue.pop) != :EOF
146 yield l
147 end
148 end
149
150 # ex)
151 # if you wish to output:
152 # "shell: job(#{@command}:#{@pid}) close pipe-out."
153 # then
154 # mes: "job(%id) close pipe-out."
155 # yorn: Boolean(@shell.debug? or @shell.verbose?)
156 def notify(*opts, &block)
157 Thread.exclusive do
158 @shell.notify(*opts) {|mes|
159 yield mes if iterator?
160
161 mes.gsub!("%id", "#{@command}:##{@pid}")
162 mes.gsub!("%name", "#{@command}")
163 mes.gsub!("%pid", "#{@pid}")
164 }
165 end
166 end
167 end
168 end