What version of Go are you using (go version)?
$ go version
go version go1.16.2 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env)?
go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/tommy/.cache/go-build"
GOENV="/home/tommy/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/tommy/go/pkg/mod"
GONOPROXY="code.xsnews.nl"
GONOSUMDB="code.xsnews.nl"
GOOS="linux"
GOPATH="/home/tommy/go"
GOPRIVATE="code.xsnews.nl"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.2"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/tommy/src/xsnews/src/ufilter/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-build1908059502=/tmp/go-build -gno-record-gcc-switches"
What did you do?
- Create a new net.Conn
- Use textproto.NewConn() to initialize the textproto connection.
- Use ReadMIMEHeader() on this textproto.Reader conn.
In this case, the canonicalMimeHeader map is uninitialized. If i would use textproto.NewReader() this map is correctly initialized using the sync.Once mechanism.
ReadMIMEHeader() uses canonicalMIMEHeaderKey() which doesn't initialize the map. If you use the public function CanonicalMIMEHeaderKey() then the map is correctly initialized.
This should fix it:
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
index 5c3084f8a7..2c10067880 100644
--- a/src/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
@@ -633,6 +633,8 @@ func validHeaderFieldByte(b byte) bool {
// For invalid inputs (if a contains spaces or non-token bytes), a
// is unchanged and a string copy is returned.
func canonicalMIMEHeaderKey(a []byte) string {
+ commonHeaderOnce.Do(initCommonHeader)
+
// See if a looks like a header key. If not, return it unchanged.
for _, c := range a {
if validHeaderFieldByte(c) {
But i believe this is a better solution: https://go-review.googlesource.com/c/go/+/170317/
What did you expect to see?
No fatal error or data race.
What did you see instead?
==================
WARNING: DATA RACE
Write at 0x000000c761c0 by goroutine 162:
code.xsnews.nl/fork/textproto.initCommonHeader()
/home/tommy/go/pkg/mod/code.xsnews.nl/fork/textproto@v0.0.0-20200302122552-071cbcc3bb82/reader.go:689 +0x64
sync.(*Once).doSlow()
/usr/local/go/src/sync/once.go:66 +0x109
sync.(*Once).Do()
/usr/local/go/src/sync/once.go:57 +0x68
code.xsnews.nl/fork/textproto.CanonicalMIMEHeaderKey()
/home/tommy/go/pkg/mod/code.xsnews.nl/fork/textproto@v0.0.0-20200302122552-071cbcc3bb82/reader.go:611 +0x64
code.xsnews.nl/fork/textproto.MIMEHeader.Get()
/home/tommy/go/pkg/mod/code.xsnews.nl/fork/textproto@v0.0.0-20200302122552-071cbcc3bb82/header.go:34 +0x54
main.writeOutFile()
/home/tommy/src/xsnews/src/ntd/cmd/collector/main.go:166 +0x1f0
main.do.func2()
/home/tommy/src/xsnews/src/ntd/cmd/collector/main.go:89 +0x38
Previous read at 0x000000c761c0 by goroutine 54:
code.xsnews.nl/fork/textproto.canonicalMIMEHeaderKey()
/home/tommy/go/pkg/mod/code.xsnews.nl/fork/textproto@v0.0.0-20200302122552-071cbcc3bb82/reader.go:677 +0x1e4
code.xsnews.nl/fork/textproto.(*Reader).ReadMIMEHeader()
/home/tommy/go/pkg/mod/code.xsnews.nl/fork/textproto@v0.0.0-20200302122552-071cbcc3bb82/reader.go:530 +0x1fb
code.xsnews.nl/lib/pnntp.NewHeaderFromTextproto()
/home/tommy/go/pkg/mod/code.xsnews.nl/lib/pnntp@v0.0.0-20200508113836-035d731406d9/reader.go:54 +0x3c
code.xsnews.nl/lib/pnntp.(*Client).Head()
/home/tommy/go/pkg/mod/code.xsnews.nl/lib/pnntp@v0.0.0-20200508113836-035d731406d9/client.go:176 +0x46b
main.importNNTPConn()
/home/tommy/src/xsnews/src/ntd/cmd/collector/main.go:118 +0x166
main.do.func1()
/home/tommy/src/xsnews/src/ntd/cmd/collector/main.go:81 +0xb6
(We forked net/textproto to better debug it but it's basically the same)
What version of Go are you using (
go version)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env)?go envOutputWhat did you do?
In this case, the canonicalMimeHeader map is uninitialized. If i would use textproto.NewReader() this map is correctly initialized using the sync.Once mechanism.
ReadMIMEHeader() uses canonicalMIMEHeaderKey() which doesn't initialize the map. If you use the public function CanonicalMIMEHeaderKey() then the map is correctly initialized.
This should fix it:
But i believe this is a better solution: https://go-review.googlesource.com/c/go/+/170317/
What did you expect to see?
No fatal error or data race.
What did you see instead?
(We forked net/textproto to better debug it but it's basically the same)