1 | #
|
---|
2 | # shell/system-command.rb -
|
---|
3 | # $Release Version: 0.6.0 $
|
---|
4 | # $Revision: 11708 $
|
---|
5 | # $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
|
---|
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.class}
|
---|
19 | Shell.Fail Error::TypeError, t.class, "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
|
---|