Class: EventMachine::POSIX::Spawn::Child::SignalHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/em/posix/spawn/child.rb

Defined Under Namespace

Classes: SignalNotifier

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSignalHandler

Returns a new instance of SignalHandler.



129
130
131
132
# File 'lib/em/posix/spawn/child.rb', line 129

def initialize
  @pid_callback = {}
  @pid_to_process_status = {}
end

Class Method Details

.instanceObject



125
126
127
# File 'lib/em/posix/spawn/child.rb', line 125

def self.instance
  @instance
end

.setup!Object



110
111
112
113
114
115
116
# File 'lib/em/posix/spawn/child.rb', line 110

def self.setup!
  @instance ||= begin
                  new.tap do |instance|
                    instance.setup!
                  end
                end
end

.teardown!Object



118
119
120
121
122
123
# File 'lib/em/posix/spawn/child.rb', line 118

def self.teardown!
  if @instance
    @instance.teardown!
    @instance = nil
  end
end

Instance Method Details

#pid_callback(pid, &blk) ⇒ Object



159
160
161
# File 'lib/em/posix/spawn/child.rb', line 159

def pid_callback(pid, &blk)
  @pid_callback[pid] = blk
end

#pid_to_process_status(pid) ⇒ Object



163
164
165
# File 'lib/em/posix/spawn/child.rb', line 163

def pid_to_process_status(pid)
  @pid_to_process_status.delete(pid)
end

#setup!Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/em/posix/spawn/child.rb', line 134

def setup!
  @pipe = ::IO.pipe
  @notifier = ::EM.watch @pipe[0], SignalNotifier, self
  @notifier.notify_readable = true

  @prev_handler = ::Signal.trap(:CHLD) do
    begin
      @pipe[1].write_nonblock("x")
    rescue IO::WaitWritable
    end

    @prev_handler.call
  end

  @prev_handler ||= lambda { |*_| ; }
end

#signalObject



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/em/posix/spawn/child.rb', line 167

def signal
  # The SIGCHLD handler may not be called exactly once for every
  # child. I.e., multiple children exiting concurrently may trigger
  # only one SIGCHLD in the parent. Therefore, reap all processes
  # that can be reaped.
  while pid = ::Process.wait(-1, ::Process::WNOHANG)
    @pid_to_process_status[pid] = $?
    blk = @pid_callback.delete(pid)
    EM.next_tick(&blk) if blk
  end
rescue ::Errno::ECHILD
end

#teardown!Object



151
152
153
154
155
156
157
# File 'lib/em/posix/spawn/child.rb', line 151

def teardown!
  ::Signal.trap(:CHLD, &@prev_handler)

  @notifier.detach if ::EM.reactor_running?
  @pipe[0].close rescue nil
  @pipe[1].close rescue nil
end