Repository: go
Issue: runtime: read scheduled on a different thread than a locked and associated with network namespace
Labels: NeedsInvestigation,compiler/runtime

<!-- Please answer these questions before submitting your issue. Thanks! -->

### What version of Go are you using (`go version`)?

Tested on 3 versions:
<pre>
$ go version
go version go1.11.13 linux/amd64
</pre>
<pre>
$ go version
go version go1.12.9 linux/amd64
</pre>
<pre>
$ go version
go version go1.13 linux/amd64
</pre>
### Does this issue reproduce with the latest release?
Not tested with 1.13.1

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go"
GOPROXY=""
GORACE=""
GOROOT="/root/golang/1.12.9"
GOTMPDIR=""
GOTOOLDIR="/root/golang/1.12.9/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/mnt/git/github/netns-go-proof/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build717114236=/tmp/go-build -gno-record-gcc-switches"
</pre></details>

### What did you do?
While working on a tool that resolves socket IDs of processes running inside Docker container I've found that reading data from procfs when a locked thread is associated with process network namespace is not deterministic. Sometimes it was reading correct data but quite ofter it was reading data from host namespace. 

With following code I was able to reproduce this issue on RHEL 7.2 - 7.6: https://github.com/difrost/netns-go-proof

Steps to reproduce using proof code:

* Find a container with a process that opens a bunch of network connections:
````bash
$ docker ps --format "{{.ID}} {{.Ports}} {{.Names}}"
96cc2a87e368 0.0.0.0:1358->1358/tcp cranky_sutherland
b78274b8892f 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp rancher
````
* Get the processes running in b78274b8892f:
````bash
$ docker top b78274b8892f -o pid,cmd
PID                 CMD
29724               tini -- rancher --http-listen-port=80 --https-listen-port=443 --audit-log-path=/var/log/auditlog/rancher-api-audit.log --audit-level=0 --audit-log-maxage=10 --audit-log-maxbackup=10 --audit-log-maxsize=100
29763               rancher --http-listen-port=80 --https-listen-port=443 --audit-log-path=/var/log/auditlog/rancher-api-audit.log --audit-level=0 --audit-log-maxage=10 --audit-log-maxbackup=10 --audit-log-maxsize=100
````
* Use [nsenter](http://man7.org/linux/man-pages/man1/nsenter.1.html) from util-linux package to count lines in /proc/net/tcp:
````bash
$ sudo nsenter -n -t 29763 cat /proc/net/tcp |wc -l
797
````
* Run proof code on 29763:
````bash
$ sudo ./NetNSBug -pid 29763
INFO[0000] Analysing 29763 in TID: 28877 PID: 28877
INFO[0000] We are in TID: 28877
INFO[0000] Got data for 29763:
INFO[0000] Got 0 lines loaded for UDP6
INFO[0000] Got 796 lines loaded for TCP
INFO[0000] Got 0 lines loaded for UDP
INFO[0000] Got 30 lines loaded for TCP6
INFO[0000] Namespace for 29763: net:[4026532507]
INFO[0000] Namespace for tid 28877: net:[4026532507]
````
* For reference host namespace TCP:
````bash
$ cat /proc/net/tcp | wc -l
5
````
* Run proof code again but this time force execution on a thread other than main one. This is done by calling [dummy goroutine](https://github.com/difrost/netns-go-proof/blob/f34ba2ab404381d4c748d08e620eb53c0763538b/main.go#L64) and granting it a bit of juice with [runtime.Gosched](https://golang.org/pkg/runtime/#Gosched).
````bash
$ sudo ./NetNSBug -pid 29763 -f
INFO[0000] Analysing 29763 in TID: 29224 PID: 29224
INFO[0000] Forcing schedule on a proper thread.
INFO[0000] We are in TID: 29226
INFO[0000] Got data for 29763:
INFO[0000] Got 6 lines loaded for UDP6
INFO[0000] Got 4 lines loaded for TCP
INFO[0000] Got 4 lines loaded for UDP
INFO[0000] Got 4 lines loaded for TCP6
INFO[0000] Namespace for 29763: net:[4026532507]
INFO[0000] Namespace for tid 29226: net:[4026532507]
````

### What did you expect to see?

Correct data read from procfs while associated with a network namespace.

### What did you see instead?

Data from host namespace.