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
158 def child
159   deactivate_contract_template(false)
160 end
parent() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
153 def parent
154   deactivate_contract_template(true)
155   abandon_latest_child_contract
156 end
prepare() click to toggle source
    # File lib/puppet/util/at_fork/solaris.rb
149 def prepare
150   activate_new_contract_template
151 end

Private Instance Methods

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