1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #1676 from maxvt/race-on-iptables-startup

Ensure iptables initialization only happens once
This commit is contained in:
Alessandro Boch 2017-03-10 15:41:31 -08:00 committed by GitHub
commit 63aae727f7

View file

@ -50,8 +50,7 @@ var (
bestEffortLock sync.Mutex bestEffortLock sync.Mutex
// ErrIptablesNotFound is returned when the rule is not found. // ErrIptablesNotFound is returned when the rule is not found.
ErrIptablesNotFound = errors.New("Iptables not found") ErrIptablesNotFound = errors.New("Iptables not found")
probeOnce sync.Once initOnce sync.Once
firewalldOnce sync.Once
) )
// ChainInfo defines the iptables chain. // ChainInfo defines the iptables chain.
@ -86,22 +85,32 @@ func initFirewalld() {
} }
} }
func detectIptables() {
path, err := exec.LookPath("iptables")
if err != nil {
return
}
iptablesPath = path
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil
mj, mn, mc, err := GetVersion()
if err != nil {
logrus.Warnf("Failed to read iptables version: %v", err)
return
}
supportsCOpt = supportsCOption(mj, mn, mc)
}
func initIptables() {
probe()
initFirewalld()
detectIptables()
}
func initCheck() error { func initCheck() error {
initOnce.Do(initIptables)
if iptablesPath == "" { if iptablesPath == "" {
probeOnce.Do(probe) return ErrIptablesNotFound
firewalldOnce.Do(initFirewalld)
path, err := exec.LookPath("iptables")
if err != nil {
return ErrIptablesNotFound
}
iptablesPath = path
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil
mj, mn, mc, err := GetVersion()
if err != nil {
logrus.Warnf("Failed to read iptables version: %v", err)
return nil
}
supportsCOpt = supportsCOption(mj, mn, mc)
} }
return nil return nil
} }
@ -373,7 +382,11 @@ func exists(native bool, table Table, chain string, rule ...string) bool {
table = Filter table = Filter
} }
initCheck() if err := initCheck(); err != nil {
// The exists() signature does not allow us to return an error, but at least
// we can skip the (likely invalid) exec invocation.
return false
}
if supportsCOpt { if supportsCOpt {
// if exit status is 0 then return true, the rule exists // if exit status is 0 then return true, the rule exists
@ -456,9 +469,9 @@ func ExistChain(chain string, table Table) bool {
return false return false
} }
// GetVersion reads the iptables version numbers // GetVersion reads the iptables version numbers during initialization
func GetVersion() (major, minor, micro int, err error) { func GetVersion() (major, minor, micro int, err error) {
out, err := Raw("--version") out, err := exec.Command(iptablesPath, "--version").CombinedOutput()
if err == nil { if err == nil {
major, minor, micro = parseVersionNumbers(string(out)) major, minor, micro = parseVersionNumbers(string(out))
} }