Shell::ProcessController

Constants

USING_AT_EXIT_WHEN_PROCESS_EXIT

for shell-command complete finish at this process exit.

Attributes

shell[R]

Public Class Methods

activate(pc) click to toggle source
 
 # File shell/process-controller.rb, line 37
def activate(pc)
 process_controllers_exclusive do
 @ProcessControllers[pc] ||= 0
 @ProcessControllers[pc] += 1
 end
end
 
active_process_controllers() click to toggle source
 
 # File shell/process-controller.rb, line 31
def active_process_controllers
 process_controllers_exclusive do
 @ProcessControllers.dup
 end
end
 
block_output_synchronize(&b) click to toggle source
 
 # File shell/process-controller.rb, line 63
def block_output_synchronize(&b)
 @BlockOutputMonitor.synchronize(&b)
end
 
each_active_object() click to toggle source
 
 # File shell/process-controller.rb, line 55
def each_active_object
 process_controllers_exclusive do
 for ref in @ProcessControllers.keys
 yield ref
 end
 end
end
 
inactivate(pc) click to toggle source
 
 # File shell/process-controller.rb, line 44
def inactivate(pc)
 process_controllers_exclusive do
 if @ProcessControllers[pc]
 if (@ProcessControllers[pc] -= 1) == 0
 @ProcessControllers.delete(pc)
 @ProcessControllersCV.signal
 end
 end
 end
end
 
new(shell) click to toggle source
 
 # File shell/process-controller.rb, line 92
def initialize(shell)
 @shell = shell
 @waiting_jobs = []
 @active_jobs = []
 @jobs_sync = Sync.new
 @job_monitor = Thread::Mutex.new
 @job_condition = Thread::ConditionVariable.new
end
 
wait_to_finish_all_process_controllers() click to toggle source
 
 # File shell/process-controller.rb, line 67
def wait_to_finish_all_process_controllers
 process_controllers_exclusive do
 while !@ProcessControllers.empty?
 Shell::notify("Process finishing, but active shell exists",
 "You can use Shell#transact or Shell#check_point for more safe execution.")
 if Shell.debug?
 for pc in @ProcessControllers.keys
 Shell::notify(" Not finished jobs in "+pc.shell.to_s)
 for com in pc.jobs
 com.notify(" Jobs: %id")
 end
 end
 end
 @ProcessControllersCV.wait(@ProcessControllersMonitor)
 end
 end
end
 

Public Instance Methods

active_job?(job) click to toggle source
 
 # File shell/process-controller.rb, line 178
def active_job?(job)
 @jobs_sync.synchronize(:SH) do
 @active_jobs.include?(job)
 end
end
 
active_jobs() click to toggle source
 
 # File shell/process-controller.rb, line 113
def active_jobs
 @active_jobs
end
 
active_jobs_exist?() click to toggle source
 
 # File shell/process-controller.rb, line 127
def active_jobs_exist?
 @jobs_sync.synchronize(:SH) do
 @active_jobs.empty?
 end
end
 
add_schedule(command) click to toggle source

schedule a command

 
 # File shell/process-controller.rb, line 140
def add_schedule(command)
 @jobs_sync.synchronize(:EX) do
 ProcessController.activate(self)
 if @active_jobs.empty?
 start_job command
 else
 @waiting_jobs.push(command)
 end
 end
end
 
jobs() click to toggle source
 
 # File shell/process-controller.rb, line 104
def jobs
 jobs = []
 @jobs_sync.synchronize(:SH) do
 jobs.concat @waiting_jobs
 jobs.concat @active_jobs
 end
 jobs
end
 
jobs_exist?() click to toggle source
 
 # File shell/process-controller.rb, line 121
def jobs_exist?
 @jobs_sync.synchronize(:SH) do
 @active_jobs.empty? or @waiting_jobs.empty?
 end
end
 
kill_job(sig, command) click to toggle source

kill a job

 
 # File shell/process-controller.rb, line 197
def kill_job(sig, command)
 @jobs_sync.synchronize(:EX) do
 if @waiting_jobs.delete command
 ProcessController.inactivate(self)
 return
 elsif @active_jobs.include?(command)
 begin
 r = command.kill(sig)
 ProcessController.inactivate(self)
 rescue
 print "Shell: Warn: $!\n" if @shell.verbose?
 return nil
 end
 @active_jobs.delete command
 r
 end
 end
end
 
sfork(command) click to toggle source

simple fork

 
 # File shell/process-controller.rb, line 233
def sfork(command)
 pipe_me_in, pipe_peer_out = IO.pipe
 pipe_peer_in, pipe_me_out = IO.pipe
 pid = nil
 pid_mutex = Thread::Mutex.new
 pid_cv = Thread::ConditionVariable.new
 Thread.start do
 ProcessController.block_output_synchronize do
 STDOUT.flush
 ProcessController.each_active_object do |pc|
 for jobs in pc.active_jobs
 jobs.flush
 end
 end
 pid = fork {
 Thread.list.each do |th|
 th.kill unless Thread.current == th
 end
 STDIN.reopen(pipe_peer_in)
 STDOUT.reopen(pipe_peer_out)
 ObjectSpace.each_object(IO) do |io|
 if ![STDIN, STDOUT, STDERR].include?(io)
 io.close
 end
 end
 yield
 }
 end
 pid_cv.signal
 pipe_peer_in.close
 pipe_peer_out.close
 command.notify "job(%name:##{pid}) start", @shell.debug?
 begin
 _pid = nil
 command.notify("job(%id) start to waiting finish.", @shell.debug?)
 _pid = Process.waitpid(pid, nil)
 rescue Errno::ECHILD
 command.notify "warn: job(%id) was done already waitpid."
 _pid = true
 ensure
 command.notify("Job(%id): Wait to finish when Process finished.", @shell.debug?)
 # when the process ends, wait until the command terminates
 if USING_AT_EXIT_WHEN_PROCESS_EXIT or _pid
 else
 command.notify("notice: Process finishing...",
 "wait for Job[%id] to finish.",
 "You can use Shell#transact or Shell#check_point for more safe execution.")
 redo
 end
 @job_monitor.synchronize do
 terminate_job(command)
 @job_condition.signal
 command.notify "job(%id) finish.", @shell.debug?
 end
 end
 end
 pid_mutex.synchronize do
 while !pid
 pid_cv.wait(pid_mutex)
 end
 end
 return pid, pipe_me_in, pipe_me_out
end
 
start_job(command = nil) click to toggle source

start a job

 
 # File shell/process-controller.rb, line 152
def start_job(command = nil)
 @jobs_sync.synchronize(:EX) do
 if command
 return if command.active?
 @waiting_jobs.delete command
 else
 command = @waiting_jobs.shift
 return unless command
 end
 @active_jobs.push command
 command.start
 # start all jobs that input from the job
 for job in @waiting_jobs.dup
 start_job(job) if job.input == command
 end
 end
end
 
terminate_job(command) click to toggle source

terminate a job

 
 # File shell/process-controller.rb, line 185
def terminate_job(command)
 @jobs_sync.synchronize(:EX) do
 @active_jobs.delete command
 ProcessController.inactivate(self)
 if @active_jobs.empty?
 command.notify("start_job in terminate_job(%id)", Shell::debug?)
 start_job
 end
 end
end
 
wait_all_jobs_execution() click to toggle source

wait for all jobs to terminate

 
 # File shell/process-controller.rb, line 217
def wait_all_jobs_execution
 @job_monitor.synchronize do
 begin
 while !jobs.empty?
 @job_condition.wait(@job_monitor)
 for job in jobs
 job.notify("waiting job(%id)", Shell::debug?)
 end
 end
 ensure
 redo unless jobs.empty?
 end
 end
end
 
waiting_job?(job) click to toggle source
 
 # File shell/process-controller.rb, line 172
def waiting_job?(job)
 @jobs_sync.synchronize(:SH) do
 @waiting_jobs.include?(job)
 end
end
 
waiting_jobs() click to toggle source
 
 # File shell/process-controller.rb, line 117
def waiting_jobs
 @waiting_jobs
end
 
waiting_jobs_exist?() click to toggle source
 
 # File shell/process-controller.rb, line 133
def waiting_jobs_exist?
 @jobs_sync.synchronize(:SH) do
 @waiting_jobs.empty?
 end
end
 

AltStyle によって変換されたページ (->オリジナル) /