Class: Yahns::Worker

Inherits:
Object
  • Object
show all
Defined in:
lib/yahns/worker.rb

Overview

Copyright © 2013-2016 all contributors <[email protected]> License: GPL-3.0+ (www.gnu.org/licenses/gpl-3.0.txt) frozen_string_literal: true

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nr) ⇒ Worker

Returns a new instance of Worker.



9
10
11
12
# File 'lib/yahns/worker.rb', line 9

def initialize(nr)
  @nr = nr
  @to_io, @wr = Kgio::Pipe.new
end

Instance Attribute Details

#nrObject

:nodoc:



6
7
8
# File 'lib/yahns/worker.rb', line 6

def nr
  @nr
end

#to_ioObject (readonly)

Returns the value of attribute to_io.



7
8
9
# File 'lib/yahns/worker.rb', line 7

def to_io
  @to_io
end

Instance Method Details

#==(other_nr) ⇒ Object

worker objects may be compared to just plain Integers



43
44
45
# File 'lib/yahns/worker.rb', line 43

def ==(other_nr) # :nodoc:
  @nr == other_nr
end

#atfork_childObject



14
15
16
# File 'lib/yahns/worker.rb', line 14

def atfork_child
  @wr = @wr.close # nil @wr to save space in worker process
end

#atfork_parentObject



18
19
20
21
# File 'lib/yahns/worker.rb', line 18

def atfork_parent
  @to_io = @to_io.close
  self
end

#fake_sig(sig) ⇒ Object

call a signal handler immediately without triggering EINTR We do not use the more obvious Process.kill(sig, $$) here since that signal delivery may be deferred. We want to avoid signal delivery while the Rack app.call is running because some database drivers (e.g. ruby-pg) may cancel pending requests.



52
53
54
55
56
57
# File 'lib/yahns/worker.rb', line 52

def fake_sig(sig) # :nodoc:
  old_cb = trap(sig, "IGNORE")
  old_cb.call
ensure
  trap(sig, old_cb)
end

#soft_kill(signum) ⇒ Object

master sends fake signals to children



60
61
62
63
64
65
66
# File 'lib/yahns/worker.rb', line 60

def soft_kill(signum) # :nodoc:
  # writing and reading 4 bytes on a pipe is atomic on all POSIX platforms
  # Do not care in the odd case the buffer is full, here.
  @wr.kgio_trywrite([signum].pack('l'))
rescue Errno::EPIPE
  # worker will be reaped soon
end

#yahns_stepObject

used in the worker process. This causes the worker to gracefully exit if the master dies unexpectedly.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/yahns/worker.rb', line 26

def yahns_step
  case buf = @to_io.kgio_tryread(4)
  when String
    # unpack the buffer and trigger the signal handler
    signum = buf.unpack('l')
    fake_sig(signum[0])
    # keep looping, more signals may be queued
  when nil # EOF: master died, but we are at a safe place to exit
    fake_sig(:QUIT)
    @to_io.close
    return :ignore
  when :wait_readable # keep waiting
    return :ignore
  end while true # loop, as multiple signals may be sent
end