diff --git a/libnetwork/libnetwork_linux_test.go b/libnetwork/libnetwork_linux_test.go index 4342aff05a..9c6b3b1d1c 100644 --- a/libnetwork/libnetwork_linux_test.go +++ b/libnetwork/libnetwork_linux_test.go @@ -850,7 +850,6 @@ func parallelJoin(t *testing.T, rc libnetwork.Sandbox, ep libnetwork.Endpoint, t err = ep.Join(sb) runtime.LockOSThread() - defer runtime.UnlockOSThread() if err != nil { if _, ok := err.(types.ForbiddenError); !ok { t.Fatalf("thread %d: %v", thrNumber, err) @@ -868,7 +867,6 @@ func parallelLeave(t *testing.T, rc libnetwork.Sandbox, ep libnetwork.Endpoint, err = ep.Leave(sb) runtime.LockOSThread() - defer runtime.UnlockOSThread() if err != nil { if _, ok := err.(types.ForbiddenError); !ok { t.Fatalf("thread %d: %v", thrNumber, err) diff --git a/libnetwork/ns/init_linux.go b/libnetwork/ns/init_linux.go index 101c3ff27f..1d08a02f52 100644 --- a/libnetwork/ns/init_linux.go +++ b/libnetwork/ns/init_linux.go @@ -39,6 +39,19 @@ func Init() { } } +// SetNamespace sets the initial namespace handler +func SetNamespace() error { + initOnce.Do(Init) + if err := netns.Set(initNs); err != nil { + linkInfo, linkErr := getLink() + if linkErr != nil { + linkInfo = linkErr.Error() + } + return fmt.Errorf("failed to set to initial namespace, %v, initns fd %d: %v", linkInfo, initNs, err) + } + return nil +} + // ParseHandlerInt transforms the namespace handler into an integer func ParseHandlerInt() int { return int(getHandler()) diff --git a/libnetwork/osl/namespace_linux.go b/libnetwork/osl/namespace_linux.go index a7c995fcc1..3e3e5f620c 100644 --- a/libnetwork/osl/namespace_linux.go +++ b/libnetwork/osl/namespace_linux.go @@ -424,10 +424,13 @@ func (n *networkNamespace) InvokeFunc(f func()) error { // InitOSContext initializes OS context while configuring network resources func InitOSContext() func() { runtime.LockOSThread() + if err := ns.SetNamespace(); err != nil { + logrus.Error(err) + } return runtime.UnlockOSThread } -func nsInvoke(path string, prefunc, postfunc func(int) error) error { +func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error { defer InitOSContext()() newNs, err := netns.GetFromPath(path) @@ -442,17 +445,10 @@ func nsInvoke(path string, prefunc, postfunc func(int) error) error { return fmt.Errorf("failed in prefunc: %v", err) } - // save the current namespace (host namespace) - curNs, err := netns.Get() - if err != nil { - return err - } - defer curNs.Close() if err = netns.Set(newNs); err != nil { return err } - // will restore the previous namespace before unlocking the thread - defer netns.Set(curNs) + defer ns.SetNamespace() // Invoked after the namespace switch. return postfunc(ns.ParseHandlerInt()) diff --git a/libnetwork/osl/sandbox_linux_test.go b/libnetwork/osl/sandbox_linux_test.go index 74053d7108..2e82c9b8c3 100644 --- a/libnetwork/osl/sandbox_linux_test.go +++ b/libnetwork/osl/sandbox_linux_test.go @@ -7,6 +7,7 @@ import ( "net" "os" "path/filepath" + "runtime" "strings" "syscall" "testing" @@ -198,6 +199,7 @@ func TestDisableIPv6DAD(t *testing.T) { if err != nil { t.Fatalf("Failed to create a new sandbox: %v", err) } + runtime.LockOSThread() defer s.Destroy() n, ok := s.(*networkNamespace) @@ -251,6 +253,7 @@ func TestSetInterfaceIP(t *testing.T) { if err != nil { t.Fatalf("Failed to create a new sandbox: %v", err) } + runtime.LockOSThread() defer s.Destroy() n, ok := s.(*networkNamespace) @@ -326,6 +329,7 @@ func TestLiveRestore(t *testing.T) { if err != nil { t.Fatalf("Failed to create a new sandbox: %v", err) } + runtime.LockOSThread() defer s.Destroy() n, ok := s.(*networkNamespace) diff --git a/libnetwork/osl/sandbox_test.go b/libnetwork/osl/sandbox_test.go index 44a0226caf..2f89fc3a10 100644 --- a/libnetwork/osl/sandbox_test.go +++ b/libnetwork/osl/sandbox_test.go @@ -2,6 +2,7 @@ package osl import ( "os" + "runtime" "testing" "github.com/docker/docker/pkg/reexec" @@ -79,6 +80,7 @@ func TestSandboxCreateTwice(t *testing.T) { if err != nil { t.Fatalf("Failed to create a new sandbox: %v", err) } + runtime.LockOSThread() // Create another sandbox with the same key to see if we handle it // gracefully. @@ -86,6 +88,7 @@ func TestSandboxCreateTwice(t *testing.T) { if err != nil { t.Fatalf("Failed to create a new sandbox: %v", err) } + runtime.LockOSThread() err = s.Destroy() if err != nil { @@ -127,6 +130,7 @@ func TestAddRemoveInterface(t *testing.T) { if err != nil { t.Fatalf("Failed to create a new sandbox: %v", err) } + runtime.LockOSThread() if s.Key() != key { t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key) diff --git a/libnetwork/testutils/context_unix.go b/libnetwork/testutils/context_unix.go index 5908c05be6..17ce4fef95 100644 --- a/libnetwork/testutils/context_unix.go +++ b/libnetwork/testutils/context_unix.go @@ -33,6 +33,8 @@ func SetupTestOSContext(t *testing.T) func() { // sure to re-initialize initNs context ns.Init() + runtime.LockOSThread() + return func() { if err := syscall.Close(fd); err != nil { t.Logf("Warning: netns closing failed (%v)", err)