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 d1b440803c
commit 2b257c922e
4 changed files with 54 additions and 0 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/armon/go-metrics/datadog" "github.com/armon/go-metrics/datadog"
"github.com/hashicorp/consul/watch" "github.com/hashicorp/consul/watch"
"github.com/hashicorp/go-checkpoint" "github.com/hashicorp/go-checkpoint"
"github.com/hashicorp/go-reap"
"github.com/hashicorp/go-syslog" "github.com/hashicorp/go-syslog"
"github.com/hashicorp/logutils" "github.com/hashicorp/logutils"
scada "github.com/hashicorp/scada-client" scada "github.com/hashicorp/scada-client"
@ -641,6 +642,32 @@ func (c *Command) Run(args []string) int {
defer server.Shutdown() 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 // Check and shut down the SCADA listeners at the end
defer func() { defer func() {
if c.scadaHttp != nil { if c.scadaHttp != nil {

View File

@ -422,6 +422,12 @@ type Config struct {
// Minimum Session TTL // Minimum Session TTL
SessionTTLMin time.Duration `mapstructure:"-"` SessionTTLMin time.Duration `mapstructure:"-"`
SessionTTLMinRaw string `mapstructure:"session_ttl_min"` 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 // 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, a.RetryJoinWan...)
result.RetryJoinWan = append(result.RetryJoinWan, b.RetryJoinWan...) result.RetryJoinWan = append(result.RetryJoinWan, b.RetryJoinWan...)
if b.DisableReap {
result.DisableReap = true
}
return &result return &result
} }

View File

@ -777,6 +777,17 @@ func TestDecodeConfig(t *testing.T) {
if config.SessionTTLMin != 5*time.Second { if config.SessionTTLMin != 5*time.Second {
t.Fatalf("bad: %s %#v", config.SessionTTLMin.String(), config) 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) { func TestDecodeConfig_invalidKeys(t *testing.T) {
@ -1157,6 +1168,7 @@ func TestMergeConfig(t *testing.T) {
CheckUpdateIntervalRaw: "8m", CheckUpdateIntervalRaw: "8m",
RetryIntervalRaw: "10s", RetryIntervalRaw: "10s",
RetryIntervalWanRaw: "10s", RetryIntervalWanRaw: "10s",
DisableReap: false,
} }
b := &Config{ b := &Config{
@ -1266,6 +1278,7 @@ func TestMergeConfig(t *testing.T) {
RPC: &net.TCPAddr{}, RPC: &net.TCPAddr{},
RPCRaw: "127.0.0.5:1233", RPCRaw: "127.0.0.5:1233",
}, },
DisableReap: true,
} }
c := MergeConfig(a, b) 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 `disable_anonymous_signature`</a> Disables providing an anonymous signature for de-duplication
with the update check. See [`disable_update_check`](#disable_update_check). 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> * <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 Disables support for remote execution. When set to true, the agent will ignore any incoming
remote exec requests. remote exec requests.