| When Facter executes an external command, it will block Ruby signal handlers from firing. This prevents things like SIGINT or SIGQUIT from terminating a Puppet process that is waiting for an external Facter command. Reproduction Case
- Install Puppet 5.5.17 or Puppet 6.11.1 on CentOS 7
yum install -y http://yum.puppetlabs.com/puppet5-release-el-7.noarch.rpm |
yum install -y puppet-agent |
|
source /etc/profile.d/puppet-agent.sh
|
- Create a custom fact that logs a message and then executes sleep:
mkdir -p /var/lib/facter/test |
cat <<EOF > /var/lib/facter/test/sleepy_fact.rb |
Facter.add(:sleepy_fact) do |
setcode do |
Facter.warn('About to sleep for 1000 seconds') |
Facter::Core::Execution.execute('/usr/bin/sleep 1000') |
'took a nice nap' |
end |
end |
EOF
|
- Run puppet facts find and attempt to cancel it with CTRL-C (SIGINT) or CTRL-\ (SIGQUIT)
FACTERLIB=/var/lib/facter/test puppet facts find
|
Outcome Like Kieth Richards, Facter cannot be killed by conventional weapons:
# FACTERLIB=/var/lib/facter/test puppet facts find |
Warning: Facter: About to sleep for 1000 seconds |
^C^C^C^C^C^C^\^\^\^\^\^\^\
|
Expected Outcome Facter executing /bin/sleep leaves the Ruby process free to respond to signals in the same way that calling Kernel.sleep does:
# cat <<EOF > /var/lib/facter/test/sleepy_fact.rb |
Facter.add(:sleepy_fact) do |
setcode do |
Facter.warn('About to sleep for 1000 seconds') |
::Kernel.sleep(1000) |
'took a nice nap' |
end |
end |
EOF |
|
# FACTERLIB=/var/lib/facter/test puppet facts find |
Warning: Facter: About to sleep for 1000 seconds |
^CCancelling Face |
Error: Facter: error while resolving custom fact "sleepy_fact": exit |
... |
|
# FACTERLIB=/var/lib/facter/test puppet facts find |
Warning: Facter: About to sleep for 1000 seconds |
^\Error: Facter: error while resolving custom fact "sleepy_fact": SIGQUIT |
...
|
|