Commit 3cbb7cbb by Ian Lance Taylor

libgo: update to Go 1.11.1 release

    
    Reviewed-on: https://go-review.googlesource.com/c/140277

From-SVN: r264932
parent a3368b8e
d0739c13ca3686df1f8d0fae7c6c5caaed058503
a9da4d34a2f878a5058f7e7d2beef52aa62471a1
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
41e62b8c49d21659b48a95216e3062032285250f
26957168c4c0cdcc7ca4f0b19d0eb19474d224ac
The first line of this file holds the git revision number of the
last merge done from the master library sources.
......@@ -1449,6 +1449,12 @@
// The directory where the go command will write
// temporary source files, packages, and binaries.
//
// Each entry in the GOFLAGS list must be a standalone flag.
// Because the entries are space-separated, flag values must
// not contain spaces. In some cases, you can provide multiple flag
// values instead: for example, to set '-ldflags=-s -w'
// you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
//
// Environment variables for use with cgo:
//
// CC
......
......@@ -507,6 +507,12 @@ General-purpose environment variables:
The directory where the go command will write
temporary source files, packages, and binaries.
Each entry in the GOFLAGS list must be a standalone flag.
Because the entries are space-separated, flag values must
not contain spaces. In some cases, you can provide multiple flag
values instead: for example, to set '-ldflags=-s -w'
you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
Environment variables for use with cgo:
CC
......
......@@ -224,7 +224,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
if len(p.SFiles) > 0 {
fmt.Fprintf(h, "asm %q %q %q\n", b.toolID("asm"), forcedAsmflags, p.Internal.Asmflags)
}
fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(cfg.BuildContext.GOARCH))) // GO386, GOARM, etc
// GO386, GOARM, GOMIPS, etc.
baseArch := strings.TrimSuffix(cfg.BuildContext.GOARCH, "le")
fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(baseArch)))
// TODO(rsc): Convince compiler team not to add more magic environment variables,
// or perhaps restrict the environment variables passed to subprocesses.
......
......@@ -170,6 +170,7 @@ var validLinkerFlags = []*regexp.Regexp{
re(`-Wl,-e[=,][a-zA-Z0-9]*`),
re(`-Wl,--enable-new-dtags`),
re(`-Wl,--end-group`),
re(`-Wl,--(no-)?export-dynamic`),
re(`-Wl,-framework,[^,@\-][^,]+`),
re(`-Wl,-headerpad_max_install_names`),
re(`-Wl,--no-undefined`),
......
......@@ -635,6 +635,9 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
text = string(data)
}
// Matching against workdir would be misleading.
text = strings.Replace(text, ts.workdir, "$WORK", -1)
if neg {
if re.MatchString(text) {
if isGrep {
......
......@@ -894,8 +894,8 @@ func validHostname(host string) bool {
if c == '-' && j != 0 {
continue
}
if c == '_' {
// _ is not a valid character in hostnames, but it's commonly
if c == '_' || c == ':' {
// Not valid characters in hostnames, but commonly
// found in deployments outside the WebPKI.
continue
}
......
......@@ -1881,6 +1881,7 @@ func TestValidHostname(t *testing.T) {
{"foo.*.example.com", false},
{"exa_mple.com", true},
{"foo,bar", false},
{"project-dev:us-central1:main", true},
}
for _, tt := range tests {
if got := validHostname(tt.host); got != tt.want {
......
......@@ -672,6 +672,7 @@ func (d *decodeState) object(v reflect.Value) error {
}
var mapElem reflect.Value
originalErrorContext := d.errorContext
for {
// Read opening " of string key or closing }.
......@@ -832,8 +833,7 @@ func (d *decodeState) object(v reflect.Value) error {
return errPhase
}
d.errorContext.Struct = ""
d.errorContext.Field = ""
d.errorContext = originalErrorContext
}
return nil
}
......@@ -991,7 +991,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
}
return &UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}
d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
case reflect.Interface:
n, err := d.convertNumber(s)
if err != nil {
......
......@@ -371,6 +371,10 @@ func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
return (*intWithMarshalText)(b).UnmarshalText(data)
}
type mapStringToStringData struct {
Data map[string]string `json:"data"`
}
type unmarshalTest struct {
in string
ptr interface{}
......@@ -401,6 +405,7 @@ var unmarshalTests = []unmarshalTest{
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
{in: "null", ptr: new(interface{}), out: nil},
{in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
{in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
{in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
......@@ -866,6 +871,18 @@ var unmarshalTests = []unmarshalTest{
err: fmt.Errorf("json: unknown field \"extra\""),
disallowUnknownFields: true,
},
// issue 26444
// UnmarshalTypeError without field & struct values
{
in: `{"data":{"test1": "bob", "test2": 123}}`,
ptr: new(mapStringToStringData),
err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 37, Struct: "mapStringToStringData", Field: "data"},
},
{
in: `{"data":{"test1": 123, "test2": "bob"}}`,
ptr: new(mapStringToStringData),
err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
},
}
func TestMarshal(t *testing.T) {
......
......@@ -262,6 +262,8 @@ func TestTypesInfo(t *testing.T) {
{`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
{`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
{`package x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
{`package x3; var x = panic("");`, `panic`, `func(interface{})`},
{`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
}
for _, test := range tests {
......
......@@ -476,7 +476,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
// panic(x)
// record panic call if inside a function with result parameters
// (for use in Checker.isTerminating)
if check.sig.results.Len() > 0 {
if check.sig != nil && check.sig.results.Len() > 0 {
// function has result parameters
p := check.isPanic
if p == nil {
......
......@@ -27,6 +27,20 @@ import (
"golang_org/x/net/dns/dnsmessage"
)
var (
errLameReferral = errors.New("lame referral")
errCannotUnmarshalDNSMessage = errors.New("cannot unmarshal DNS message")
errCannotMarshalDNSMessage = errors.New("cannot marshal DNS message")
errServerMisbehaving = errors.New("server misbehaving")
errInvalidDNSResponse = errors.New("invalid DNS response")
errNoAnswerFromDNSServer = errors.New("no answer from DNS server")
// errServerTemporarlyMisbehaving is like errServerMisbehaving, except
// that when it gets translated to a DNSError, the IsTemporary field
// gets set to true.
errServerTemporarlyMisbehaving = errors.New("server misbehaving")
)
func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) {
id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true})
......@@ -105,14 +119,14 @@ func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
var p dnsmessage.Parser
h, err := p.Start(b[:n])
if err != nil {
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
}
q, err := p.Question()
if err != nil {
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
}
if !checkResponse(id, query, h, q) {
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
}
return p, h, nil
}
......@@ -122,7 +136,7 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
q.Class = dnsmessage.ClassINET
id, udpReq, tcpReq, err := newRequest(q)
if err != nil {
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot marshal DNS message")
return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotMarshalDNSMessage
}
for _, network := range []string{"udp", "tcp"} {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
......@@ -147,31 +161,31 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
return dnsmessage.Parser{}, dnsmessage.Header{}, mapErr(err)
}
if err := p.SkipQuestion(); err != dnsmessage.ErrSectionDone {
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
}
if h.Truncated { // see RFC 5966
continue
}
return p, h, nil
}
return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("no answer from DNS server")
return dnsmessage.Parser{}, dnsmessage.Header{}, errNoAnswerFromDNSServer
}
// checkHeader performs basic sanity checks on the header.
func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string) error {
if h.RCode == dnsmessage.RCodeNameError {
return errNoSuchHost
}
_, err := p.AnswerHeader()
if err != nil && err != dnsmessage.ErrSectionDone {
return &DNSError{
Err: "cannot unmarshal DNS message",
Name: name,
Server: server,
}
return errCannotUnmarshalDNSMessage
}
// libresolv continues to the next server when it receives
// an invalid referral response. See golang.org/issue/15434.
if h.RCode == dnsmessage.RCodeSuccess && !h.Authoritative && !h.RecursionAvailable && err == dnsmessage.ErrSectionDone {
return &DNSError{Err: "lame referral", Name: name, Server: server}
return errLameReferral
}
if h.RCode != dnsmessage.RCodeSuccess && h.RCode != dnsmessage.RCodeNameError {
......@@ -180,11 +194,10 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string)
// a name error and we didn't get success,
// the server is behaving incorrectly or
// having temporary trouble.
err := &DNSError{Err: "server misbehaving", Name: name, Server: server}
if h.RCode == dnsmessage.RCodeServerFailure {
err.IsTemporary = true
return errServerTemporarlyMisbehaving
}
return err
return errServerMisbehaving
}
return nil
......@@ -194,28 +207,16 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type, name, server stri
for {
h, err := p.AnswerHeader()
if err == dnsmessage.ErrSectionDone {
return &DNSError{
Err: errNoSuchHost.Error(),
Name: name,
Server: server,
}
return errNoSuchHost
}
if err != nil {
return &DNSError{
Err: "cannot unmarshal DNS message",
Name: name,
Server: server,
}
return errCannotUnmarshalDNSMessage
}
if h.Type == qtype {
return nil
}
if err := p.SkipAnswer(); err != nil {
return &DNSError{
Err: "cannot unmarshal DNS message",
Name: name,
Server: server,
}
return errCannotUnmarshalDNSMessage
}
}
}
......@@ -229,7 +230,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
n, err := dnsmessage.NewName(name)
if err != nil {
return dnsmessage.Parser{}, "", errors.New("cannot marshal DNS message")
return dnsmessage.Parser{}, "", errCannotMarshalDNSMessage
}
q := dnsmessage.Question{
Name: n,
......@@ -243,38 +244,62 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
p, h, err := r.exchange(ctx, server, q, cfg.timeout)
if err != nil {
lastErr = &DNSError{
dnsErr := &DNSError{
Err: err.Error(),
Name: name,
Server: server,
}
if nerr, ok := err.(Error); ok && nerr.Timeout() {
lastErr.(*DNSError).IsTimeout = true
dnsErr.IsTimeout = true
}
// Set IsTemporary for socket-level errors. Note that this flag
// may also be used to indicate a SERVFAIL response.
if _, ok := err.(*OpError); ok {
lastErr.(*DNSError).IsTemporary = true
dnsErr.IsTemporary = true
}
lastErr = dnsErr
continue
}
// The name does not exist, so trying another server won't help.
//
// TODO: indicate this in a more obvious way, such as a field on DNSError?
if h.RCode == dnsmessage.RCodeNameError {
return dnsmessage.Parser{}, "", &DNSError{Err: errNoSuchHost.Error(), Name: name, Server: server}
}
lastErr = checkHeader(&p, h, name, server)
if lastErr != nil {
if err := checkHeader(&p, h, name, server); err != nil {
dnsErr := &DNSError{
Err: err.Error(),
Name: name,
Server: server,
}
if err == errServerTemporarlyMisbehaving {
dnsErr.IsTemporary = true
}
if err == errNoSuchHost {
// The name does not exist, so trying
// another server won't help.
//
// TODO: indicate this in a more
// obvious way, such as a field on
// DNSError?
return p, server, dnsErr
}
lastErr = dnsErr
continue
}
lastErr = skipToAnswer(&p, qtype, name, server)
if lastErr == nil {
err = skipToAnswer(&p, qtype, name, server)
if err == nil {
return p, server, nil
}
lastErr = &DNSError{
Err: err.Error(),
Name: name,
Server: server,
}
if err == errNoSuchHost {
// The name does not exist, so trying another
// server won't help.
//
// TODO: indicate this in a more obvious way,
// such as a field on DNSError?
return p, server, lastErr
}
}
}
return dnsmessage.Parser{}, "", lastErr
......
......@@ -1427,28 +1427,35 @@ func TestDNSGoroutineRace(t *testing.T) {
}
}
func lookupWithFake(fake fakeDNSServer, name string, typ dnsmessage.Type) error {
r := Resolver{PreferGo: true, Dial: fake.DialContext}
resolvConf.mu.RLock()
conf := resolvConf.dnsConfig
resolvConf.mu.RUnlock()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, _, err := r.tryOneName(ctx, conf, name, typ)
return err
}
// Issue 8434: verify that Temporary returns true on an error when rcode
// is SERVFAIL
func TestIssue8434(t *testing.T) {
msg := dnsmessage.Message{
Header: dnsmessage.Header{
RCode: dnsmessage.RCodeServerFailure,
err := lookupWithFake(fakeDNSServer{
rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
return dnsmessage.Message{
Header: dnsmessage.Header{
ID: q.ID,
Response: true,
RCode: dnsmessage.RCodeServerFailure,
},
Questions: q.Questions,
}, nil
},
}
b, err := msg.Pack()
if err != nil {
t.Fatal("Pack failed:", err)
}
var p dnsmessage.Parser
h, err := p.Start(b)
if err != nil {
t.Fatal("Start failed:", err)
}
if err := p.SkipAllQuestions(); err != nil {
t.Fatal("SkipAllQuestions failed:", err)
}
err = checkHeader(&p, h, "golang.org", "foo:53")
}, "golang.org.", dnsmessage.TypeALL)
if err == nil {
t.Fatal("expected an error")
}
......@@ -1464,50 +1471,76 @@ func TestIssue8434(t *testing.T) {
}
}
// Issue 12778: verify that NXDOMAIN without RA bit errors as
// "no such host" and not "server misbehaving"
// TestNoSuchHost verifies that tryOneName works correctly when the domain does
// not exist.
//
// Issue 12778: verify that NXDOMAIN without RA bit errors as "no such host"
// and not "server misbehaving"
//
// Issue 25336: verify that NXDOMAIN errors fail fast.
func TestIssue12778(t *testing.T) {
lookups := 0
fake := fakeDNSServer{
rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
lookups++
return dnsmessage.Message{
Header: dnsmessage.Header{
ID: q.ID,
Response: true,
RCode: dnsmessage.RCodeNameError,
RecursionAvailable: false,
},
Questions: q.Questions,
}, nil
//
// Issue 27525: verify that empty answers fail fast.
func TestNoSuchHost(t *testing.T) {
tests := []struct {
name string
f func(string, string, dnsmessage.Message, time.Time) (dnsmessage.Message, error)
}{
{
"NXDOMAIN",
func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
return dnsmessage.Message{
Header: dnsmessage.Header{
ID: q.ID,
Response: true,
RCode: dnsmessage.RCodeNameError,
RecursionAvailable: false,
},
Questions: q.Questions,
}, nil
},
},
{
"no answers",
func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
return dnsmessage.Message{
Header: dnsmessage.Header{
ID: q.ID,
Response: true,
RCode: dnsmessage.RCodeSuccess,
RecursionAvailable: false,
Authoritative: true,
},
Questions: q.Questions,
}, nil
},
},
}
r := Resolver{PreferGo: true, Dial: fake.DialContext}
resolvConf.mu.RLock()
conf := resolvConf.dnsConfig
resolvConf.mu.RUnlock()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, _, err := r.tryOneName(ctx, conf, ".", dnsmessage.TypeALL)
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
lookups := 0
err := lookupWithFake(fakeDNSServer{
rh: func(n, s string, q dnsmessage.Message, d time.Time) (dnsmessage.Message, error) {
lookups++
return test.f(n, s, q, d)
},
}, ".", dnsmessage.TypeALL)
if lookups != 1 {
t.Errorf("got %d lookups, wanted 1", lookups)
}
if lookups != 1 {
t.Errorf("got %d lookups, wanted 1", lookups)
}
if err == nil {
t.Fatal("expected an error")
}
de, ok := err.(*DNSError)
if !ok {
t.Fatalf("err = %#v; wanted a *net.DNSError", err)
}
if de.Err != errNoSuchHost.Error() {
t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
if err == nil {
t.Fatal("expected an error")
}
de, ok := err.(*DNSError)
if !ok {
t.Fatalf("err = %#v; wanted a *net.DNSError", err)
}
if de.Err != errNoSuchHost.Error() {
t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
}
})
}
}
......@@ -1535,3 +1568,56 @@ func TestDNSDialTCP(t *testing.T) {
t.Fatal("exhange failed:", err)
}
}
// Issue 27763: verify that two strings in one TXT record are concatenated.
func TestTXTRecordTwoStrings(t *testing.T) {
fake := fakeDNSServer{
rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
r := dnsmessage.Message{
Header: dnsmessage.Header{
ID: q.Header.ID,
Response: true,
RCode: dnsmessage.RCodeSuccess,
},
Questions: q.Questions,
Answers: []dnsmessage.Resource{
{
Header: dnsmessage.ResourceHeader{
Name: q.Questions[0].Name,
Type: dnsmessage.TypeA,
Class: dnsmessage.ClassINET,
},
Body: &dnsmessage.TXTResource{
TXT: []string{"string1 ", "string2"},
},
},
{
Header: dnsmessage.ResourceHeader{
Name: q.Questions[0].Name,
Type: dnsmessage.TypeA,
Class: dnsmessage.ClassINET,
},
Body: &dnsmessage.TXTResource{
TXT: []string{"onestring"},
},
},
},
}
return r, nil
},
}
r := Resolver{PreferGo: true, Dial: fake.DialContext}
txt, err := r.lookupTXT(context.Background(), "golang.org")
if err != nil {
t.Fatal("LookupTXT failed:", err)
}
if want := 2; len(txt) != want {
t.Fatalf("len(txt), got %d, want %d", len(txt), want)
}
if want := "string1 string2"; txt[0] != want {
t.Errorf("txt[0], got %q, want %q", txt[0], want)
}
if want := "onestring"; txt[1] != want {
t.Errorf("txt[1], got %q, want %q", txt[1], want)
}
}
......@@ -116,7 +116,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
b := result.Get("body")
var body io.ReadCloser
if b != js.Undefined() {
// The body is undefined when the browser does not support streaming response bodies (Firefox),
// and null in certain error cases, i.e. when the request is blocked because of CORS settings.
if b != js.Undefined() && b != js.Null() {
body = &streamReader{stream: b.Call("getReader")}
} else {
// Fall back to using ArrayBuffer
......
......@@ -299,11 +299,21 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
Server: server,
}
}
// Multiple strings in one TXT record need to be
// concatenated without separator to be consistent
// with previous Go resolver.
n := 0
for _, s := range txt.TXT {
n += len(s)
}
txtJoin := make([]byte, 0, n)
for _, s := range txt.TXT {
txtJoin = append(txtJoin, s...)
}
if len(txts) == 0 {
txts = txt.TXT
} else {
txts = append(txts, txt.TXT...)
txts = make([]string, 0, 1)
}
txts = append(txts, string(txtJoin))
}
return txts, nil
}
......
......@@ -124,6 +124,7 @@ func testSpliceBig(t *testing.T) {
func testSpliceHonorsLimitedReader(t *testing.T) {
t.Run("stopsAfterN", testSpliceStopsAfterN)
t.Run("updatesN", testSpliceUpdatesN)
t.Run("readerAtLimit", testSpliceReaderAtLimit)
}
func testSpliceStopsAfterN(t *testing.T) {
......@@ -210,7 +211,7 @@ func testSpliceUpdatesN(t *testing.T) {
}
}
func testSpliceReaderAtEOF(t *testing.T) {
func testSpliceReaderAtLimit(t *testing.T) {
clientUp, serverUp, err := spliceTestSocketPair("tcp")
if err != nil {
t.Fatal(err)
......@@ -224,22 +225,64 @@ func testSpliceReaderAtEOF(t *testing.T) {
defer clientDown.Close()
defer serverDown.Close()
serverUp.Close()
_, err, handled := splice(serverDown.(*TCPConn).fd, serverUp)
lr := &io.LimitedReader{
N: 0,
R: serverUp,
}
_, err, handled := splice(serverDown.(*TCPConn).fd, lr)
if !handled {
if serr, ok := err.(*os.SyscallError); ok && serr.Syscall == "pipe2" && serr.Err == syscall.ENOSYS {
t.Skip("pipe2 not supported")
}
t.Errorf("closed connection: got err = %v, handled = %t, want handled = true", err, handled)
t.Errorf("exhausted LimitedReader: got err = %v, handled = %t, want handled = true", err, handled)
}
lr := &io.LimitedReader{
N: 0,
R: serverUp,
}
func testSpliceReaderAtEOF(t *testing.T) {
clientUp, serverUp, err := spliceTestSocketPair("tcp")
if err != nil {
t.Fatal(err)
}
_, err, handled = splice(serverDown.(*TCPConn).fd, lr)
if !handled {
t.Errorf("exhausted LimitedReader: got err = %v, handled = %t, want handled = true", err, handled)
defer clientUp.Close()
clientDown, serverDown, err := spliceTestSocketPair("tcp")
if err != nil {
t.Fatal(err)
}
defer clientDown.Close()
serverUp.Close()
// We'd like to call net.splice here and check the handled return
// value, but we disable splice on old Linux kernels.
//
// In that case, poll.Splice and net.splice return a non-nil error
// and handled == false. We'd ideally like to see handled == true
// because the source reader is at EOF, but if we're running on an old
// kernel, and splice is disabled, we won't see EOF from net.splice,
// because we won't touch the reader at all.
//
// Trying to untangle the errors from net.splice and match them
// against the errors created by the poll package would be brittle,
// so this is a higher level test.
//
// The following ReadFrom should return immediately, regardless of
// whether splice is disabled or not. The other side should then
// get a goodbye signal. Test for the goodbye signal.
msg := "bye"
go func() {
serverDown.(*TCPConn).ReadFrom(serverUp)
io.WriteString(serverDown, msg)
serverDown.Close()
}()
buf := make([]byte, 3)
_, err = io.ReadFull(clientDown, buf)
if err != nil {
t.Errorf("clientDown: %v", err)
}
if string(buf) != msg {
t.Errorf("clientDown got %q, want %q", buf, msg)
}
}
......
......@@ -5864,7 +5864,7 @@ func clobber() {
type funcLayoutTest struct {
rcvr, t Type
size, argsize, retOffset uintptr
stack []byte // pointer bitmap: 1 is pointer, 0 is scalar (or uninitialized)
stack []byte // pointer bitmap: 1 is pointer, 0 is scalar
gc []byte
}
......@@ -5886,7 +5886,7 @@ func init() {
6 * PtrSize,
4 * PtrSize,
4 * PtrSize,
[]byte{1, 0, 1},
[]byte{1, 0, 1, 0, 1},
[]byte{1, 0, 1, 0, 1},
})
......
......@@ -33,7 +33,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
ap := params
for _, rt := range ftyp.in {
p := unsafe_New(rt)
memmove(p, *(*unsafe.Pointer)(ap), rt.size)
typedmemmove(rt, p, *(*unsafe.Pointer)(ap))
v := Value{rt, p, flag(rt.Kind()) | flagIndir}
in = append(in, v)
ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
......@@ -59,7 +59,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
*(*unsafe.Pointer)(addr) = v.ptr
} else {
memmove(addr, v.ptr, typ.size)
typedmemmove(typ, addr, v.ptr)
}
off += typ.size
}
......
......@@ -323,7 +323,7 @@ var callGC bool // for testing; see TestCallMethodJump
func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
t := v.typ
t := (*funcType)(unsafe.Pointer(v.typ))
var (
fn unsafe.Pointer
rcvr Value
......@@ -472,7 +472,7 @@ func (v Value) call(op string, in []Value) []Value {
// The return value rcvrtype gives the method's actual receiver type.
// The return value t gives the method type signature (without the receiver).
// The return value fn is a pointer to the method code.
func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *funcType, fn unsafe.Pointer) {
i := methodIndex
if v.typ.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(v.typ))
......@@ -489,7 +489,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
}
rcvrtype = iface.itab.typ
fn = unsafe.Pointer(&iface.itab.fun[i])
t = m.typ
t = (*funcType)(unsafe.Pointer(m.typ))
} else {
rcvrtype = v.typ
ms := v.typ.exportedMethods()
......@@ -501,7 +501,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
panic("reflect: " + op + " of unexported method")
}
fn = unsafe.Pointer(&m.tfn)
t = m.mtyp
t = (*funcType)(unsafe.Pointer(m.mtyp))
}
return
}
......@@ -2399,10 +2399,14 @@ func mapiternext(it unsafe.Pointer)
//go:noescape
func maplen(m unsafe.Pointer) int
func call(typ *rtype, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
func call(typ *funcType, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
// memmove copies size bytes to dst from src. No write barriers are used.
//go:noescape
func memmove(dst, src unsafe.Pointer, size uintptr)
// typedmemmove copies a value of type t to dst from src.
//go:noescape
func typedmemmove(t *rtype, dst, src unsafe.Pointer)
......@@ -2412,10 +2416,6 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
//go:noescape
func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
//go:noescape
//extern memmove
func memmove(adst, asrc unsafe.Pointer, n uintptr)
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
......
......@@ -102,7 +102,7 @@ func makechan(t *chantype, size int) *hchan {
// Queue or element size is zero.
c = (*hchan)(mallocgc(hchanSize, nil, true))
// Race detector uses this location for synchronization.
c.buf = unsafe.Pointer(c)
c.buf = c.raceaddr()
case elem.kind&kindNoPointers != 0:
// Elements do not contain pointers.
// Allocate hchan and buf in one call.
......@@ -166,7 +166,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
}
if raceenabled {
racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend))
racereadpc(c.raceaddr(), callerpc, funcPC(chansend))
}
// Fast path: check for failed non-blocking operation without acquiring the lock.
......@@ -352,8 +352,8 @@ func closechan(c *hchan) {
if raceenabled {
callerpc := getcallerpc()
racewritepc(unsafe.Pointer(c), callerpc, funcPC(closechan))
racerelease(unsafe.Pointer(c))
racewritepc(c.raceaddr(), callerpc, funcPC(closechan))
racerelease(c.raceaddr())
}
c.closed = 1
......@@ -376,7 +376,7 @@ func closechan(c *hchan) {
gp := sg.g
gp.param = nil
if raceenabled {
raceacquireg(gp, unsafe.Pointer(c))
raceacquireg(gp, c.raceaddr())
}
gp.schedlink.set(glist)
glist = gp
......@@ -395,7 +395,7 @@ func closechan(c *hchan) {
gp := sg.g
gp.param = nil
if raceenabled {
raceacquireg(gp, unsafe.Pointer(c))
raceacquireg(gp, c.raceaddr())
}
gp.schedlink.set(glist)
glist = gp
......@@ -477,7 +477,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
if c.closed != 0 && c.qcount == 0 {
if raceenabled {
raceacquire(unsafe.Pointer(c))
raceacquire(c.raceaddr())
}
unlock(&c.lock)
if ep != nil {
......@@ -755,6 +755,15 @@ func (q *waitq) dequeue() *sudog {
}
}
func (c *hchan) raceaddr() unsafe.Pointer {
// Treat read-like and write-like operations on the channel to
// happen at this address. Avoid using the address of qcount
// or dataqsiz, because the len() and cap() builtins read
// those addresses, and we don't want them racing with
// operations like close().
return unsafe.Pointer(&c.buf)
}
func racesync(c *hchan, sg *sudog) {
racerelease(chanbuf(c, 0))
raceacquireg(sg.g, chanbuf(c, 0))
......
......@@ -309,6 +309,19 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
memclrNoHeapPointers(ptr, typ.size)
}
//go:linkname reflect_typedmemclr reflect.typedmemclr
func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) {
typedmemclr(typ, ptr)
}
//go:linkname reflect_typedmemclrpartial reflect.typedmemclrpartial
func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintptr) {
if typ.kind&kindNoPointers == 0 {
bulkBarrierPreWrite(uintptr(ptr), 0, size)
}
memclrNoHeapPointers(ptr, size)
}
// memclrHasPointers clears n bytes of typed memory starting at ptr.
// The caller must ensure that the type of the object at ptr has
// pointers, usually by checking typ.kind&kindNoPointers. However, ptr
......
......@@ -34,6 +34,10 @@ func semacreate(mp *m) {
//go:nosplit
func semasleep(ns int64) int32 {
var start int64
if ns >= 0 {
start = nanotime()
}
mp := getg().m
pthread_mutex_lock(&mp.mutex)
for {
......@@ -43,8 +47,13 @@ func semasleep(ns int64) int32 {
return 0
}
if ns >= 0 {
spent := nanotime() - start
if spent >= ns {
pthread_mutex_unlock(&mp.mutex)
return -1
}
var t timespec
t.set_nsec(ns)
t.set_nsec(ns - spent)
err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
if err == _ETIMEDOUT {
pthread_mutex_unlock(&mp.mutex)
......
......@@ -29,15 +29,9 @@ func semacreate(mp *m) {
//go:nosplit
func semasleep(ns int64) int32 {
_g_ := getg()
// Compute sleep deadline.
var tsp *timespec
var ts timespec
var deadline int64
if ns >= 0 {
var nsec int32
ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
ts.set_nsec(nsec)
tsp = &ts
deadline = nanotime() + ns
}
for {
......@@ -50,18 +44,21 @@ func semasleep(ns int64) int32 {
}
// Sleep until unparked by semawakeup or timeout.
var tsp *timespec
var ts timespec
if ns >= 0 {
wait := deadline - nanotime()
if wait <= 0 {
return -1
}
var nsec int32
ts.set_sec(timediv(wait, 1000000000, &nsec))
ts.set_nsec(nsec)
tsp = &ts
}
ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
if ret == _ETIMEDOUT {
return -1
} else if ret == _EINTR && ns >= 0 {
// Avoid sleeping forever if we keep getting
// interrupted (for example by the profiling
// timer). It would be if tsp upon return had the
// remaining time to sleep, but this is good enough.
var nsec int32
ns /= 2
ts.set_sec(timediv(ns, 1000000000, &nsec))
ts.set_nsec(nsec)
}
}
}
......
......@@ -426,7 +426,7 @@ rclose:
typedmemclr(c.elemtype, cas.elem)
}
if raceenabled {
raceacquire(unsafe.Pointer(c))
raceacquire(c.raceaddr())
}
goto retc
......
......@@ -24,13 +24,13 @@ type traceContextKey struct{}
// If the end function is called multiple times, only the first
// call is used in the latency measurement.
//
// ctx, task := trace.NewTask(ctx, "awesome task")
// trace.WithRegion(ctx, prepWork)
// ctx, task := trace.NewTask(ctx, "awesomeTask")
// trace.WithRegion(ctx, "preparation", prepWork)
// // preparation of the task
// go func() { // continue processing the task in a separate goroutine.
// defer task.End()
// trace.WithRegion(ctx, remainingWork)
// }
// trace.WithRegion(ctx, "remainingWork", remainingWork)
// }()
func NewTask(pctx context.Context, taskType string) (ctx context.Context, task *Task) {
pid := fromContext(pctx).id
id := newID()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment