Merge pull request #182 from rosenhouse/document-lockosthread
Document use of goroutine and LockOSThread in test helpers
This commit is contained in:
commit
57b28f3936
@ -52,6 +52,33 @@ func GetInodeF(file *os.File) (uint64, error) {
|
|||||||
return stat.Ino, err
|
return stat.Ino, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
A note about goroutines, Linux namespaces and runtime.LockOSThread
|
||||||
|
|
||||||
|
In Linux, network namespaces have thread affinity.
|
||||||
|
|
||||||
|
In the Go language runtime, goroutines do not have affinity for OS threads.
|
||||||
|
The Go runtime scheduler moves goroutines around amongst OS threads. It
|
||||||
|
is supposed to be transparent to the Go programmer.
|
||||||
|
|
||||||
|
In order to address cases where the programmer needs thread affinity, Go
|
||||||
|
provides runtime.LockOSThread and runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
However, the Go runtime does not reference count the Lock and Unlock calls.
|
||||||
|
Repeated calls to Lock will succeed, but the first call to Unlock will unlock
|
||||||
|
everything. Therefore, it is dangerous to hide a Lock/Unlock in a library
|
||||||
|
function, such as in this package.
|
||||||
|
|
||||||
|
The code below, in MakeNetworkNS, avoids this problem by spinning up a new
|
||||||
|
Go routine specifically so that LockOSThread can be called on it. Thus
|
||||||
|
goroutine-thread affinity is maintained long enough to perform all the required
|
||||||
|
namespace operations.
|
||||||
|
|
||||||
|
Because the LockOSThread call is performed inside this short-lived goroutine,
|
||||||
|
there is no effect either way on the caller's goroutine-thread affinity.
|
||||||
|
|
||||||
|
* */
|
||||||
|
|
||||||
func MakeNetworkNS(containerID string) string {
|
func MakeNetworkNS(containerID string) string {
|
||||||
namespace := "/var/run/netns/" + containerID
|
namespace := "/var/run/netns/" + containerID
|
||||||
|
|
||||||
@ -68,7 +95,7 @@ func MakeNetworkNS(containerID string) string {
|
|||||||
|
|
||||||
// do namespace work in a dedicated goroutine, so that we can safely
|
// do namespace work in a dedicated goroutine, so that we can safely
|
||||||
// Lock/Unlock OSThread without upsetting the lock/unlock state of
|
// Lock/Unlock OSThread without upsetting the lock/unlock state of
|
||||||
// the caller of this function
|
// the caller of this function. See block comment above.
|
||||||
go (func() {
|
go (func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user