Class: ChildManager

Inherits:
Object
  • Object
show all
Defined in:
lib/xing/managers/child.rb

Defined Under Namespace

Classes: ChildRecord

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeChildManager

Returns a new instance of ChildManager.



2
3
4
5
6
# File 'lib/xing/managers/child.rb', line 2

def initialize
  @child_pids = []
  @parent_pid = Process.pid
  @child_data = {}
end

Instance Attribute Details

#child_dataObject

Returns the value of attribute child_data.



7
8
9
# File 'lib/xing/managers/child.rb', line 7

def child_data
  @child_data
end

#child_pidsObject

Returns the value of attribute child_pids.



7
8
9
# File 'lib/xing/managers/child.rb', line 7

def child_pids
  @child_pids
end

Instance Method Details

#exited?(pid) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/xing/managers/child.rb', line 27

def exited?(pid)
  return false unless child_data.has_key?(pid)
  return true unless child_data[pid].status.nil?

  begin
    _apid, status = *Process.wait2(pid, Process::WNOHANG | Process::WUNTRACED)
  rescue Errno::ECHILD
    return false
  end

  unless status.nil?
    child_data[pid].status = status
    return true
  end
  return false
end

#kill_allObject



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/xing/managers/child.rb', line 85

def kill_all
  unless Process.pid == @parent_pid
    puts "Although #{Process.pid} was asked to kill all, it isn't #@parent_pid the original parent"
    return
  end
  child_pids.each do |pid|
    kill_child(pid)
  end
  previous_term_trap = trap "TERM" do
    puts "Trapped TERM once"
    trap "TERM", previous_term_trap
  end
  Process::kill("TERM", 0)
end

#kill_child(pid) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/xing/managers/child.rb', line 48

def kill_child(pid)
  unless Process.pid == @parent_pid
    puts "#{Process.pid} #@parent_pid Not original parent: not killing"
    return
  end
  puts "PID #{Process.pid} is killing child #{pid} #{child_data[pid].name}"

  if exited?(pid)
    puts "#{pid} #{child_data[pid].name} already exited"
    return
  end

  begin
    Process::kill("TERM", pid)
  rescue Errno::ESRCH
    puts "Hm. #{pid} is already gone: dead?"
    return
  end

  limit = 10
  start = Time.now
  while Time.now - start < limit
    begin
      Process::kill(0, pid)
      sleep(0.1)
    rescue Errno::ESRCH
      return
    end
  end

  begin
    Process::kill("KILL", pid)
  rescue Errno::ESRCH
    return
  end
end

#start_child(name, task) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/xing/managers/child.rb', line 11

def start_child(name, task)
  child_pid = Process.fork do
    Signal.trap("HUP") do
      puts "Parent exited"
      exit
    end

    exec(*(%w{bundle exec rake} + [task]))
  end
  puts "#{@parent_pid}: #{name} running in pid #{child_pid}"

  at_exit { kill_child(child_pid) }
  child_data[child_pid] = ChildRecord.new(name, nil)
  child_pids << child_pid
end

#wait_allObject



44
45
46
# File 'lib/xing/managers/child.rb', line 44

def wait_all
  Process.waitall
end