From 44ef10948340e07f4b58a5443a881b4b0c69a5da Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 17 Nov 2016 15:45:38 +0000 Subject: [PATCH] Expand description of goroutine+netns problems --- ns/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ns/README.md b/ns/README.md index e7b20c2f..99aed9c8 100644 --- a/ns/README.md +++ b/ns/README.md @@ -9,7 +9,7 @@ Go provides the `runtime.LockOSThread()` function to ensure a specific goroutine For example, you cannot rely on the `ns.Set()` namespace being the current namespace after the `Set()` call unless you do two things. First, the goroutine calling `Set()` must have previously called `LockOSThread()`. Second, you must ensure `runtime.UnlockOSThread()` is not called somewhere in-between. You also cannot rely on the initial network namespace remaining the current network namespace if any other code in your program switches namespaces, unless you have already called `LockOSThread()` in that goroutine. Note that `LockOSThread()` prevents the Go scheduler from optimally scheduling goroutines for best performance, so `LockOSThread()` should only be used in small, isolated goroutines that release the lock quickly. ### Do() The Recommended Thing -The `ns.Do()` method provides control over network namespaces for you by implementing these strategies. All code dependent on a particular network namespace should be wrapped in the `ns.Do()` method to ensure the correct namespace is selected for the duration of your code. For example: +The `ns.Do()` method provides control over network namespaces for you by implementing these strategies. All code dependent on a particular network namespace (including the root namespace) should be wrapped in the `ns.Do()` method to ensure the correct namespace is selected for the duration of your code. For example: ```go targetNs, err := ns.NewNS() @@ -26,6 +26,9 @@ err = targetNs.Do(func(hostNs ns.NetNS) error { }) ``` +Note this requirement to wrap every network call is very onerous - any libraries you call might call out to network services such as DNS, and all such calls need to be protected after you call `ns.Do()`. The CNI plugins all exit very soon after calling `ns.Do()` which helps to minimize the problem. + ### Further Reading - https://github.com/golang/go/wiki/LockOSThread - http://morsmachine.dk/go-scheduler + - https://github.com/containernetworking/cni/issues/262