mirror of
https://github.com/vishvananda/netns
synced 2025-02-16 19:46:49 +00:00
Fix handling of namespaces in multi-threaded processes.
GetFromPid gets the namespace of the main thread, so previously Get returned the wrong value if run from any other thread. Add a new GetFromThread which uses the Linux thread id and switch Get to it.
This commit is contained in:
parent
e14a2d4e90
commit
008d17ae00
@ -47,7 +47,7 @@ func New() (ns NsHandle, err error) {
|
|||||||
|
|
||||||
// Get gets a handle to the current threads network namespace.
|
// Get gets a handle to the current threads network namespace.
|
||||||
func Get() (NsHandle, error) {
|
func Get() (NsHandle, error) {
|
||||||
return GetFromPid(os.Getpid())
|
return GetFromThread(os.Getpid(), syscall.Gettid())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFromName gets a handle to a named network namespace such as one
|
// GetFromName gets a handle to a named network namespace such as one
|
||||||
@ -60,7 +60,7 @@ func GetFromName(name string) (NsHandle, error) {
|
|||||||
return NsHandle(fd), nil
|
return NsHandle(fd), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFromName gets a handle to the network namespace of a given pid.
|
// GetFromPid gets a handle to the network namespace of a given pid.
|
||||||
func GetFromPid(pid int) (NsHandle, error) {
|
func GetFromPid(pid int) (NsHandle, error) {
|
||||||
fd, err := syscall.Open(fmt.Sprintf("/proc/%d/ns/net", pid), syscall.O_RDONLY, 0)
|
fd, err := syscall.Open(fmt.Sprintf("/proc/%d/ns/net", pid), syscall.O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,7 +69,17 @@ func GetFromPid(pid int) (NsHandle, error) {
|
|||||||
return NsHandle(fd), nil
|
return NsHandle(fd), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFromName gets a handle to the network namespace of a docker container.
|
// GetFromThread gets a handle to the network namespace of a given pid and tid.
|
||||||
|
func GetFromThread(pid, tid int) (NsHandle, error) {
|
||||||
|
name := fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid)
|
||||||
|
fd, err := syscall.Open(name, syscall.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return NsHandle(fd), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFromDocker gets a handle to the network namespace of a docker container.
|
||||||
// Id is prefixed matched against the running docker containers, so a short
|
// Id is prefixed matched against the running docker containers, so a short
|
||||||
// identifier can be used as long as it isn't ambiguous.
|
// identifier can be used as long as it isn't ambiguous.
|
||||||
func GetFromDocker(id string) (NsHandle, error) {
|
func GetFromDocker(id string) (NsHandle, error) {
|
||||||
@ -169,7 +179,7 @@ func getPidForContainer(id string) (int, error) {
|
|||||||
return pid, fmt.Errorf("Ambiguous id supplied: %v", filenames)
|
return pid, fmt.Errorf("Ambiguous id supplied: %v", filenames)
|
||||||
} else if len(filenames) == 1 {
|
} else if len(filenames) == 1 {
|
||||||
filename = filenames[0]
|
filename = filenames[0]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package netns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,3 +43,24 @@ func TestNone(t *testing.T) {
|
|||||||
t.Fatal("None ns is open", ns)
|
t.Fatal("None ns is open", ns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestThreaded(t *testing.T) {
|
||||||
|
ncpu := runtime.GOMAXPROCS(-1)
|
||||||
|
if ncpu < 2 {
|
||||||
|
t.Skip("-cpu=2 or larger required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock this thread simply to ensure other threads get used.
|
||||||
|
runtime.LockOSThread()
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
for i := 0; i < ncpu; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
TestGetNewSetDelete(t)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user