diff options
Diffstat (limited to 'lib/yahns/worker.rb')
-rw-r--r-- | lib/yahns/worker.rb | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/yahns/worker.rb b/lib/yahns/worker.rb new file mode 100644 index 0000000..980f7bd --- /dev/null +++ b/lib/yahns/worker.rb @@ -0,0 +1,58 @@ +# -*- encoding: binary -*- +# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors +# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +class Yahns::Worker # :nodoc: + attr_accessor :nr + attr_reader :to_io + + def initialize(nr) + @nr = nr + @to_io, @wr = Kgio::Pipe.new + end + + def atfork_child + @wr = @wr.close # nil @wr to save space in worker process + end + + def atfork_parent + @to_io = @to_io.close + self + end + + # used in the worker process. + # This causes the worker to gracefully exit if the master + # dies unexpectedly. + def yahns_step + @to_io.kgio_tryread(11) == nil and Process.kill(:QUIT, $$) + :wait_readable + end + + # worker objects may be compared to just plain Integers + def ==(other_nr) # :nodoc: + @nr == other_nr + end + + # Changes the worker process to the specified +user+ and +group+ + # This is only intended to be called from within the worker + # process from the +after_fork+ hook. This should be called in + # the +after_fork+ hook after any privileged functions need to be + # run (e.g. to set per-worker CPU affinity, niceness, etc) + # + # Any and all errors raised within this method will be propagated + # directly back to the caller (usually the +after_fork+ hook. + # These errors commonly include ArgumentError for specifying an + # invalid user/group and Errno::EPERM for insufficient privileges + def user(user, group = nil) + # we do not protect the caller, checking Process.euid == 0 is + # insufficient because modern systems have fine-grained + # capabilities. Let the caller handle any and all errors. + uid = Etc.getpwnam(user).uid + gid = Etc.getgrnam(group).gid if group + Yahns::Log.chown_all(uid, gid) + if gid && Process.egid != gid + Process.initgroups(user, gid) + Process::GID.change_privilege(gid) + end + Process.euid != uid and Process::UID.change_privilege(uid) + end +end |