class Puppet::Util::AtFork::Solaris

Solaris implementation of the Puppet::Util::AtFork handler. The callbacks defined in this implementation ensure the forked process runs in a different contract than the parent process. This is necessary in order for the child process to be able to survive termination of the contract its parent process runs in. This is needed notably for an agent run executed by a puppet agent service to be able to restart that service without being killed in the process as a consequence of running in the same contract as the service, as all processes in the contract are killed when the contract is terminated during the service restart.

Constants

CTD_COMMON
CTFS_PR_LATEST
CTFS_PR_ROOT
CTFS_PR_TEMPLATE
CT_PR_EV_HWERR
CT_PR_PGRPONLY

Public Instance Methods

child() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
157 def child
158   deactivate_contract_template(false)
159 end
parent() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
152 def parent
153   deactivate_contract_template(true)
154   abandon_latest_child_contract
155 end
prepare() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
148 def prepare
149   activate_new_contract_template
150 end

Private Instance Methods

abandon_latest_child_contract() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
129 def abandon_latest_child_contract
130   ctid = get_latest_child_contract_id
131   return if ctid.nil?
132 
133   begin
134     ctl = File.open(File.join(CTFS_PR_ROOT, ctid.to_s, %q(ctl)), File::WRONLY)
135 
136     begin
137       raise_if_error { ct_ctl_abandon(ctl.fileno) }
138     ensure
139       ctl.close
140     end
141   rescue => detail
142     Puppet.log_exception(detail, _('Failed to abandon a child process contract'))
143   end
144 end
activate_new_contract_template() click to toggle source
   # File lib/puppet/util/at_fork/solaris.rb
63 def activate_new_contract_template
64   begin
65     tmpl = File.open(CTFS_PR_TEMPLATE, File::RDWR)
66 
67     begin
68       tmpl_fd = tmpl.fileno
69 
70       raise_if_error { ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) }
71       raise_if_error { ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) }
72       raise_if_error { ct_tmpl_set_critical(tmpl_fd, 0) }
73       raise_if_error { ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) }
74 
75       raise_if_error { ct_tmpl_activate(tmpl_fd) }
76     rescue
77       tmpl.close
78       raise
79     end
80 
81     @tmpl = tmpl
82   rescue => detail
83     Puppet.log_exception(detail, _('Failed to activate a new process contract template'))
84   end
85 end
deactivate_contract_template(parent) click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
 87 def deactivate_contract_template(parent)
 88   return if @tmpl.nil?
 89 
 90   tmpl = @tmpl
 91   @tmpl = nil
 92 
 93   begin
 94     raise_if_error { ct_tmpl_clear(tmpl.fileno) }
 95   rescue => detail
 96     msg = if parent
 97             _('Failed to deactivate process contract template in the parent process')
 98           else
 99             _('Failed to deactivate process contract template in the child process')
100           end
101     Puppet.log_exception(detail, msg)
102     exit(1)
103   ensure
104     tmpl.close
105   end
106 end
get_latest_child_contract_id() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
108 def get_latest_child_contract_id
109   begin
110     stat = File.open(CTFS_PR_LATEST, File::RDONLY)
111 
112     begin
113       stathdl = Fiddle::Pointer.new(0)
114 
115       raise_if_error { ct_status_read(stat.fileno, CTD_COMMON, stathdl.ref) }
116       ctid = ct_status_get_id(stathdl)
117       ct_status_free(stathdl)
118     ensure
119       stat.close
120     end
121 
122     ctid
123   rescue => detail
124     Puppet.log_exception(detail, _('Failed to get latest child process contract id'))
125     nil
126   end
127 end
raise_if_error() { || ... } click to toggle source
   # File lib/puppet/util/at_fork/solaris.rb
56 def raise_if_error(&block)
57   unless (e = yield) == 0
58     e = SystemCallError.new(nil, e)
59     raise e, e.message, caller
60   end
61 end