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

libnetwork/testutils: restore netns on teardown

testutils.SetupTestOSContext() sets the calling thread's network
namespace but neglected to restore it on teardown. This was not a
problem in practice as it called runtime.LockOSThread() twice but
runtime.UnlockOSThread() only once, so the tampered threads would be
terminated by the runtime when the test case returned and replaced with
a clean thread. Correct the utility so it restores the thread's network
namespace during teardown and unlocks the goroutine from the thread on
success.

Remove unnecessary runtime.LockOSThread() calls peppering test cases
which leverage testutils.SetupTestOSContext().

Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
Cory Snider 2022-10-24 11:42:22 -04:00
parent 40b3fc727d
commit afa41b16ea
2 changed files with 24 additions and 17 deletions

View file

@ -7,7 +7,6 @@ import (
"net"
"os"
"path/filepath"
"runtime"
"strings"
"syscall"
"testing"
@ -197,7 +196,6 @@ func TestDisableIPv6DAD(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create a new sandbox: %v", err)
}
runtime.LockOSThread()
defer destroyTest(t, s)
n, ok := s.(*networkNamespace)
@ -257,7 +255,6 @@ func TestSetInterfaceIP(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create a new sandbox: %v", err)
}
runtime.LockOSThread()
defer destroyTest(t, s)
n, ok := s.(*networkNamespace)
@ -332,7 +329,6 @@ func TestLiveRestore(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create a new sandbox: %v", err)
}
runtime.LockOSThread()
defer destroyTest(t, s)
n, ok := s.(*networkNamespace)
@ -482,7 +478,6 @@ 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.
@ -490,7 +485,6 @@ 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 {
@ -532,7 +526,6 @@ 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)

View file

@ -5,10 +5,10 @@ package testutils
import (
"runtime"
"syscall"
"testing"
"github.com/docker/docker/libnetwork/ns"
"github.com/vishvananda/netns"
)
// SetupTestOSContext joins a new network namespace, and returns its associated
@ -18,26 +18,40 @@ import (
//
// defer SetupTestOSContext(t)()
func SetupTestOSContext(t *testing.T) func() {
runtime.LockOSThread()
if err := syscall.Unshare(syscall.CLONE_NEWNET); err != nil {
t.Fatalf("Failed to enter netns: %v", err)
origNS, err := netns.Get()
if err != nil {
t.Fatalf("Failed to open initial netns: %v", err)
}
restore := func() {
if err := netns.Set(origNS); err != nil {
t.Logf("Warning: failed to restore thread netns (%v)", err)
} else {
runtime.UnlockOSThread()
}
if err := origNS.Close(); err != nil {
t.Logf("Warning: netns closing failed (%v)", err)
}
}
fd, err := syscall.Open("/proc/self/ns/net", syscall.O_RDONLY, 0)
runtime.LockOSThread()
newNS, err := netns.New()
if err != nil {
t.Fatal("Failed to open netns file")
// netns.New() is not atomic: it could have encountered an error
// after unsharing the current thread's network namespace.
restore()
t.Fatalf("Failed to enter netns: %v", err)
}
// Since we are switching to a new test namespace make
// sure to re-initialize initNs context
ns.Init()
runtime.LockOSThread()
return func() {
if err := syscall.Close(fd); err != nil {
if err := newNS.Close(); err != nil {
t.Logf("Warning: netns closing failed (%v)", err)
}
runtime.UnlockOSThread()
restore()
ns.Init()
}
}