mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-11 01:30:55 +08:00
libgo: update to Go 1.11.1 release
Reviewed-on: https://go-review.googlesource.com/c/140277 From-SVN: r264932
This commit is contained in:
parent
a3368b8ea1
commit
3cbb7cbb09
@ -1,4 +1,4 @@
|
||||
d0739c13ca3686df1f8d0fae7c6c5caaed058503
|
||||
a9da4d34a2f878a5058f7e7d2beef52aa62471a1
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -1,4 +1,4 @@
|
||||
41e62b8c49d21659b48a95216e3062032285250f
|
||||
26957168c4c0cdcc7ca4f0b19d0eb19474d224ac
|
||||
|
||||
The first line of this file holds the git revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
@ -1 +1 @@
|
||||
go1.11
|
||||
go1.11.1
|
||||
|
@ -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()
|
||||
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)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
if lookups != 1 {
|
||||
t.Errorf("got %d lookups, wanted 1", lookups)
|
||||
}
|
||||
|
||||
_, _, err := r.tryOneName(ctx, conf, ".", dnsmessage.TypeALL)
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
if len(txts) == 0 {
|
||||
txts = txt.TXT
|
||||
} else {
|
||||
txts = append(txts, txt.TXT...)
|
||||
// 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 = 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,25 +225,67 @@ 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)
|
||||
}
|
||||
lr := &io.LimitedReader{
|
||||
N: 0,
|
||||
R: serverUp,
|
||||
}
|
||||
_, err, handled = splice(serverDown.(*TCPConn).fd, lr)
|
||||
if !handled {
|
||||
t.Errorf("exhausted LimitedReader: got err = %v, handled = %t, want handled = true", err, handled)
|
||||
}
|
||||
}
|
||||
|
||||
func testSpliceReaderAtEOF(t *testing.T) {
|
||||
clientUp, serverUp, err := spliceTestSocketPair("tcp")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func testSpliceIssue25985(t *testing.T) {
|
||||
front, err := newLocalListener("tcp")
|
||||
if err != nil {
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user