1 # -*- encoding: binary -*-
4 # This class and its members can be considered a stable interface
5 # and will not change in a backwards-incompatible fashion between
6 # releases of \Unicorn. Knowledge of this class is generally not
7 # not needed for most users of \Unicorn.
9 # Some users may want to access it in the before_fork/after_fork hooks.
10 # See the Unicorn::Configurator RDoc for examples.
13 attr_accessor :nr, :switched
16 PER_DROP = Raindrops::PAGE_SIZE / Raindrops::SIZE
20 drop_index = nr / PER_DROP
21 @raindrop = DROPS[drop_index] ||= Raindrops.new(PER_DROP)
22 @offset = nr % PER_DROP
23 @raindrop[@offset] = 0
25 @tmp = @switched = false
28 # worker objects may be compared to just plain Integers
29 def ==(other_nr) # :nodoc:
33 # called in the worker process
34 def tick=(value) # :nodoc:
35 @raindrop[@offset] = value
38 # called in the master process
43 # only exists for compatibility
46 tmp = Unicorn::TmpIO.new
47 tmp.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
58 # In most cases, you should be using the Unicorn::Configurator#user
59 # directive instead. This method should only be used if you need
60 # fine-grained control of exactly when you want to change permissions
61 # in your after_fork hooks.
63 # Changes the worker process to the specified +user+ and +group+
64 # This is only intended to be called from within the worker
65 # process from the +after_fork+ hook. This should be called in
66 # the +after_fork+ hook after any privileged functions need to be
67 # run (e.g. to set per-worker CPU affinity, niceness, etc)
69 # Any and all errors raised within this method will be propagated
70 # directly back to the caller (usually the +after_fork+ hook.
71 # These errors commonly include ArgumentError for specifying an
72 # invalid user/group and Errno::EPERM for insufficient privileges
73 def user(user, group = nil)
74 # we do not protect the caller, checking Process.euid == 0 is
75 # insufficient because modern systems have fine-grained
76 # capabilities. Let the caller handle any and all errors.
77 uid = Etc.getpwnam(user).uid
78 gid = Etc.getgrnam(group).gid if group
79 Unicorn::Util.chown_logs(uid, gid)
80 @tmp.chown(uid, gid) if @tmp
81 if gid && Process.egid != gid
82 Process.initgroups(user, gid)
83 Process::GID.change_privilege(gid)
85 Process.euid != uid and Process::UID.change_privilege(uid)