Adds child process reaping when Consul is running as PID 1.

This commit is contained in:
James Phillips 2015-12-21 21:47:35 -08:00
parent 7d4462f1c5
commit 1e4aa28c9d
4 changed files with 54 additions and 0 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/armon/go-metrics/datadog"
"github.com/hashicorp/consul/watch"
"github.com/hashicorp/go-checkpoint"
"github.com/hashicorp/go-reap"
"github.com/hashicorp/go-syslog"
"github.com/hashicorp/logutils"
scada "github.com/hashicorp/scada-client"
@ -641,6 +642,32 @@ func (c *Command) Run(args []string) int {
defer server.Shutdown()
}
// Enable child process reaping
if !config.DisableReap && (os.Getpid() == 1) {
logger := c.agent.logger
if !reap.IsSupported() {
logger.Printf("[WARN] Running as PID 1 but child process reaping is not supported on this platform, disabling")
} else {
logger.Printf("[DEBUG] Automatically reaping child processes")
pids := make(reap.PidCh, 1)
errors := make(reap.ErrorCh, 1)
go func() {
for {
select {
case pid := <-pids:
logger.Printf("[DEBUG] Reaped child process %d", pid)
case err := <-errors:
logger.Printf("[ERR] Error reaping child process: %v", err)
case <-c.agent.shutdownCh:
return
}
}
}()
go reap.ReapChildren(pids, errors, c.agent.shutdownCh)
}
}
// Check and shut down the SCADA listeners at the end
defer func() {
if c.scadaHttp != nil {

View File

@ -422,6 +422,12 @@ type Config struct {
// Minimum Session TTL
SessionTTLMin time.Duration `mapstructure:"-"`
SessionTTLMinRaw string `mapstructure:"session_ttl_min"`
// DisableReap controls automatic reaping of child processes, useful if
// running as PID 1 in a Docker container. This defaults to false, and
// reaping will be automatically enabled if this is false and Consul's
// PID is 1.
DisableReap bool `mapstructure:"disable_reap"`
}
// UnixSocketPermissions contains information about a unix socket, and
@ -1140,6 +1146,10 @@ func MergeConfig(a, b *Config) *Config {
result.RetryJoinWan = append(result.RetryJoinWan, a.RetryJoinWan...)
result.RetryJoinWan = append(result.RetryJoinWan, b.RetryJoinWan...)
if b.DisableReap {
result.DisableReap = true
}
return &result
}

View File

@ -777,6 +777,17 @@ func TestDecodeConfig(t *testing.T) {
if config.SessionTTLMin != 5*time.Second {
t.Fatalf("bad: %s %#v", config.SessionTTLMin.String(), config)
}
// DisableReap
input = `{"disable_reap": true}`
config, err = DecodeConfig(bytes.NewReader([]byte(input)))
if err != nil {
t.Fatalf("err: %s", err)
}
if config.DisableReap != true {
t.Fatalf("bad: reap not disabled: %#v", config)
}
}
func TestDecodeConfig_invalidKeys(t *testing.T) {
@ -1157,6 +1168,7 @@ func TestMergeConfig(t *testing.T) {
CheckUpdateIntervalRaw: "8m",
RetryIntervalRaw: "10s",
RetryIntervalWanRaw: "10s",
DisableReap: false,
}
b := &Config{
@ -1266,6 +1278,7 @@ func TestMergeConfig(t *testing.T) {
RPC: &net.TCPAddr{},
RPCRaw: "127.0.0.5:1233",
},
DisableReap: true,
}
c := MergeConfig(a, b)

View File

@ -407,6 +407,10 @@ definitions support being updated during a reload.
`disable_anonymous_signature`</a> Disables providing an anonymous signature for de-duplication
with the update check. See [`disable_update_check`](#disable_update_check).
* <a name="disable_reap"></a><a href="#disable_reap">
`disable_reap`</a> will prevent Consul from automatically reaping child processes if it
detects it is running as PID 1, such as in a Docker container.
* <a name="disable_remote_exec"></a><a href="#disable_remote_exec">`disable_remote_exec`</a>
Disables support for remote execution. When set to true, the agent will ignore any incoming
remote exec requests.