Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
3cbb7cbb
Commit
3cbb7cbb
authored
Oct 08, 2018
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
libgo: update to Go 1.11.1 release
Reviewed-on:
https://go-review.googlesource.com/c/140277
From-SVN: r264932
parent
a3368b8e
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
399 additions
and
167 deletions
+399
-167
gcc/go/gofrontend/MERGE
+1
-1
libgo/MERGE
+1
-1
libgo/VERSION
+1
-1
libgo/go/cmd/go/alldocs.go
+6
-0
libgo/go/cmd/go/internal/help/helpdoc.go
+6
-0
libgo/go/cmd/go/internal/work/exec.go
+3
-1
libgo/go/cmd/go/internal/work/security.go
+1
-0
libgo/go/cmd/go/script_test.go
+3
-0
libgo/go/crypto/x509/verify.go
+2
-2
libgo/go/crypto/x509/verify_test.go
+1
-0
libgo/go/encoding/json/decode.go
+3
-3
libgo/go/encoding/json/decode_test.go
+17
-0
libgo/go/go/types/api_test.go
+2
-0
libgo/go/go/types/builtins.go
+1
-1
libgo/go/net/dnsclient_unix.go
+70
-45
libgo/go/net/dnsclient_unix_test.go
+141
-55
libgo/go/net/http/roundtrip_js.go
+3
-1
libgo/go/net/lookup_unix.go
+13
-3
libgo/go/net/splice_test.go
+53
-10
libgo/go/reflect/all_test.go
+2
-2
libgo/go/reflect/makefunc_ffi.go
+2
-2
libgo/go/reflect/value.go
+9
-9
libgo/go/runtime/chan.go
+16
-7
libgo/go/runtime/mbarrier.go
+13
-0
libgo/go/runtime/os_darwin.go
+10
-1
libgo/go/runtime/os_netbsd.go
+14
-17
libgo/go/runtime/select.go
+1
-1
libgo/go/runtime/trace/annotation.go
+4
-4
No files found.
gcc/go/gofrontend/MERGE
View file @
3cbb7cbb
d0739c13ca3686df1f8d0fae7c6c5caaed058503
a9da4d34a2f878a5058f7e7d2beef52aa62471a1
The first line of this file holds the git revision number of the last
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
merge done from the gofrontend repository.
libgo/MERGE
View file @
3cbb7cbb
41e62b8c49d21659b48a95216e3062032285250f
26957168c4c0cdcc7ca4f0b19d0eb19474d224ac
The first line of this file holds the git revision number of the
The first line of this file holds the git revision number of the
last merge done from the master library sources.
last merge done from the master library sources.
libgo/VERSION
View file @
3cbb7cbb
go1.11
go1.11
.1
libgo/go/cmd/go/alldocs.go
View file @
3cbb7cbb
...
@@ -1449,6 +1449,12 @@
...
@@ -1449,6 +1449,12 @@
// The directory where the go command will write
// The directory where the go command will write
// temporary source files, packages, and binaries.
// 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:
// Environment variables for use with cgo:
//
//
// CC
// CC
...
...
libgo/go/cmd/go/internal/help/helpdoc.go
View file @
3cbb7cbb
...
@@ -507,6 +507,12 @@ General-purpose environment variables:
...
@@ -507,6 +507,12 @@ General-purpose environment variables:
The directory where the go command will write
The directory where the go command will write
temporary source files, packages, and binaries.
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:
Environment variables for use with cgo:
CC
CC
...
...
libgo/go/cmd/go/internal/work/exec.go
View file @
3cbb7cbb
...
@@ -224,7 +224,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
...
@@ -224,7 +224,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
if
len
(
p
.
SFiles
)
>
0
{
if
len
(
p
.
SFiles
)
>
0
{
fmt
.
Fprintf
(
h
,
"asm %q %q %q
\n
"
,
b
.
toolID
(
"asm"
),
forcedAsmflags
,
p
.
Internal
.
Asmflags
)
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,
// TODO(rsc): Convince compiler team not to add more magic environment variables,
// or perhaps restrict the environment variables passed to subprocesses.
// or perhaps restrict the environment variables passed to subprocesses.
...
...
libgo/go/cmd/go/internal/work/security.go
View file @
3cbb7cbb
...
@@ -170,6 +170,7 @@ var validLinkerFlags = []*regexp.Regexp{
...
@@ -170,6 +170,7 @@ var validLinkerFlags = []*regexp.Regexp{
re
(
`-Wl,-e[=,][a-zA-Z0-9]*`
),
re
(
`-Wl,-e[=,][a-zA-Z0-9]*`
),
re
(
`-Wl,--enable-new-dtags`
),
re
(
`-Wl,--enable-new-dtags`
),
re
(
`-Wl,--end-group`
),
re
(
`-Wl,--end-group`
),
re
(
`-Wl,--(no-)?export-dynamic`
),
re
(
`-Wl,-framework,[^,@\-][^,]+`
),
re
(
`-Wl,-framework,[^,@\-][^,]+`
),
re
(
`-Wl,-headerpad_max_install_names`
),
re
(
`-Wl,-headerpad_max_install_names`
),
re
(
`-Wl,--no-undefined`
),
re
(
`-Wl,--no-undefined`
),
...
...
libgo/go/cmd/go/script_test.go
View file @
3cbb7cbb
...
@@ -635,6 +635,9 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
...
@@ -635,6 +635,9 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
text
=
string
(
data
)
text
=
string
(
data
)
}
}
// Matching against workdir would be misleading.
text
=
strings
.
Replace
(
text
,
ts
.
workdir
,
"$WORK"
,
-
1
)
if
neg
{
if
neg
{
if
re
.
MatchString
(
text
)
{
if
re
.
MatchString
(
text
)
{
if
isGrep
{
if
isGrep
{
...
...
libgo/go/crypto/x509/verify.go
View file @
3cbb7cbb
...
@@ -894,8 +894,8 @@ func validHostname(host string) bool {
...
@@ -894,8 +894,8 @@ func validHostname(host string) bool {
if
c
==
'-'
&&
j
!=
0
{
if
c
==
'-'
&&
j
!=
0
{
continue
continue
}
}
if
c
==
'_'
{
if
c
==
'_'
||
c
==
':'
{
//
_ is not a valid character in hostnames, but it's
commonly
//
Not valid characters in hostnames, but
commonly
// found in deployments outside the WebPKI.
// found in deployments outside the WebPKI.
continue
continue
}
}
...
...
libgo/go/crypto/x509/verify_test.go
View file @
3cbb7cbb
...
@@ -1881,6 +1881,7 @@ func TestValidHostname(t *testing.T) {
...
@@ -1881,6 +1881,7 @@ func TestValidHostname(t *testing.T) {
{
"foo.*.example.com"
,
false
},
{
"foo.*.example.com"
,
false
},
{
"exa_mple.com"
,
true
},
{
"exa_mple.com"
,
true
},
{
"foo,bar"
,
false
},
{
"foo,bar"
,
false
},
{
"project-dev:us-central1:main"
,
true
},
}
}
for
_
,
tt
:=
range
tests
{
for
_
,
tt
:=
range
tests
{
if
got
:=
validHostname
(
tt
.
host
);
got
!=
tt
.
want
{
if
got
:=
validHostname
(
tt
.
host
);
got
!=
tt
.
want
{
...
...
libgo/go/encoding/json/decode.go
View file @
3cbb7cbb
...
@@ -672,6 +672,7 @@ func (d *decodeState) object(v reflect.Value) error {
...
@@ -672,6 +672,7 @@ func (d *decodeState) object(v reflect.Value) error {
}
}
var
mapElem
reflect
.
Value
var
mapElem
reflect
.
Value
originalErrorContext
:=
d
.
errorContext
for
{
for
{
// Read opening " of string key or closing }.
// Read opening " of string key or closing }.
...
@@ -832,8 +833,7 @@ func (d *decodeState) object(v reflect.Value) error {
...
@@ -832,8 +833,7 @@ func (d *decodeState) object(v reflect.Value) error {
return
errPhase
return
errPhase
}
}
d
.
errorContext
.
Struct
=
""
d
.
errorContext
=
originalErrorContext
d
.
errorContext
.
Field
=
""
}
}
return
nil
return
nil
}
}
...
@@ -991,7 +991,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
...
@@ -991,7 +991,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if
fromQuoted
{
if
fromQuoted
{
return
fmt
.
Errorf
(
"json: invalid use of ,string struct tag, trying to unmarshal %q into %v"
,
item
,
v
.
Type
())
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
:
case
reflect
.
Interface
:
n
,
err
:=
d
.
convertNumber
(
s
)
n
,
err
:=
d
.
convertNumber
(
s
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
libgo/go/encoding/json/decode_test.go
View file @
3cbb7cbb
...
@@ -371,6 +371,10 @@ func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
...
@@ -371,6 +371,10 @@ func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
return
(
*
intWithMarshalText
)(
b
)
.
UnmarshalText
(
data
)
return
(
*
intWithMarshalText
)(
b
)
.
UnmarshalText
(
data
)
}
}
type
mapStringToStringData
struct
{
Data
map
[
string
]
string
`json:"data"`
}
type
unmarshalTest
struct
{
type
unmarshalTest
struct
{
in
string
in
string
ptr
interface
{}
ptr
interface
{}
...
@@ -401,6 +405,7 @@ var unmarshalTests = []unmarshalTest{
...
@@ -401,6 +405,7 @@ var unmarshalTests = []unmarshalTest{
{
in
:
`"invalid: \uD834x\uDD1E"`
,
ptr
:
new
(
string
),
out
:
"invalid:
\uFFFD
x
\uFFFD
"
},
{
in
:
`"invalid: \uD834x\uDD1E"`
,
ptr
:
new
(
string
),
out
:
"invalid:
\uFFFD
x
\uFFFD
"
},
{
in
:
"null"
,
ptr
:
new
(
interface
{}),
out
:
nil
},
{
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": [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
),
out
:
tx
{}},
{
in
:
`{"x": 1}`
,
ptr
:
new
(
tx
),
err
:
fmt
.
Errorf
(
"json: unknown field
\"
x
\"
"
),
disallowUnknownFields
:
true
},
{
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"
)}},
{
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{
...
@@ -866,6 +871,18 @@ var unmarshalTests = []unmarshalTest{
err
:
fmt
.
Errorf
(
"json: unknown field
\"
extra
\"
"
),
err
:
fmt
.
Errorf
(
"json: unknown field
\"
extra
\"
"
),
disallowUnknownFields
:
true
,
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
)
{
func
TestMarshal
(
t
*
testing
.
T
)
{
...
...
libgo/go/go/types/api_test.go
View file @
3cbb7cbb
...
@@ -262,6 +262,8 @@ func TestTypesInfo(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 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 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 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
{
for
_
,
test
:=
range
tests
{
...
...
libgo/go/go/types/builtins.go
View file @
3cbb7cbb
...
@@ -476,7 +476,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
...
@@ -476,7 +476,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
// panic(x)
// panic(x)
// record panic call if inside a function with result parameters
// record panic call if inside a function with result parameters
// (for use in Checker.isTerminating)
// (for use in Checker.isTerminating)
if
check
.
sig
.
results
.
Len
()
>
0
{
if
check
.
sig
!=
nil
&&
check
.
sig
.
results
.
Len
()
>
0
{
// function has result parameters
// function has result parameters
p
:=
check
.
isPanic
p
:=
check
.
isPanic
if
p
==
nil
{
if
p
==
nil
{
...
...
libgo/go/net/dnsclient_unix.go
View file @
3cbb7cbb
...
@@ -27,6 +27,20 @@ import (
...
@@ -27,6 +27,20 @@ import (
"golang_org/x/net/dns/dnsmessage"
"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
)
{
func
newRequest
(
q
dnsmessage
.
Question
)
(
id
uint16
,
udpReq
,
tcpReq
[]
byte
,
err
error
)
{
id
=
uint16
(
rand
.
Int
())
^
uint16
(
time
.
Now
()
.
UnixNano
())
id
=
uint16
(
rand
.
Int
())
^
uint16
(
time
.
Now
()
.
UnixNano
())
b
:=
dnsmessage
.
NewBuilder
(
make
([]
byte
,
2
,
514
),
dnsmessage
.
Header
{
ID
:
id
,
RecursionDesired
:
true
})
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)
...
@@ -105,14 +119,14 @@ func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
var
p
dnsmessage
.
Parser
var
p
dnsmessage
.
Parser
h
,
err
:=
p
.
Start
(
b
[
:
n
])
h
,
err
:=
p
.
Start
(
b
[
:
n
])
if
err
!=
nil
{
if
err
!=
nil
{
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
ors
.
New
(
"cannot unmarshal DNS message"
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
CannotUnmarshalDNSMessage
}
}
q
,
err
:=
p
.
Question
()
q
,
err
:=
p
.
Question
()
if
err
!=
nil
{
if
err
!=
nil
{
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
ors
.
New
(
"cannot unmarshal DNS message"
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
CannotUnmarshalDNSMessage
}
}
if
!
checkResponse
(
id
,
query
,
h
,
q
)
{
if
!
checkResponse
(
id
,
query
,
h
,
q
)
{
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
ors
.
New
(
"invalid DNS response"
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
InvalidDNSResponse
}
}
return
p
,
h
,
nil
return
p
,
h
,
nil
}
}
...
@@ -122,7 +136,7 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
...
@@ -122,7 +136,7 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
q
.
Class
=
dnsmessage
.
ClassINET
q
.
Class
=
dnsmessage
.
ClassINET
id
,
udpReq
,
tcpReq
,
err
:=
newRequest
(
q
)
id
,
udpReq
,
tcpReq
,
err
:=
newRequest
(
q
)
if
err
!=
nil
{
if
err
!=
nil
{
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
ors
.
New
(
"cannot marshal DNS message"
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
CannotMarshalDNSMessage
}
}
for
_
,
network
:=
range
[]
string
{
"udp"
,
"tcp"
}
{
for
_
,
network
:=
range
[]
string
{
"udp"
,
"tcp"
}
{
ctx
,
cancel
:=
context
.
WithDeadline
(
ctx
,
time
.
Now
()
.
Add
(
timeout
))
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
...
@@ -147,31 +161,31 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
mapErr
(
err
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
mapErr
(
err
)
}
}
if
err
:=
p
.
SkipQuestion
();
err
!=
dnsmessage
.
ErrSectionDone
{
if
err
:=
p
.
SkipQuestion
();
err
!=
dnsmessage
.
ErrSectionDone
{
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
ors
.
New
(
"invalid DNS response"
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
InvalidDNSResponse
}
}
if
h
.
Truncated
{
// see RFC 5966
if
h
.
Truncated
{
// see RFC 5966
continue
continue
}
}
return
p
,
h
,
nil
return
p
,
h
,
nil
}
}
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
ors
.
New
(
"no answer from DNS server"
)
return
dnsmessage
.
Parser
{},
dnsmessage
.
Header
{},
err
NoAnswerFromDNSServer
}
}
// checkHeader performs basic sanity checks on the header.
// checkHeader performs basic sanity checks on the header.
func
checkHeader
(
p
*
dnsmessage
.
Parser
,
h
dnsmessage
.
Header
,
name
,
server
string
)
error
{
func
checkHeader
(
p
*
dnsmessage
.
Parser
,
h
dnsmessage
.
Header
,
name
,
server
string
)
error
{
if
h
.
RCode
==
dnsmessage
.
RCodeNameError
{
return
errNoSuchHost
}
_
,
err
:=
p
.
AnswerHeader
()
_
,
err
:=
p
.
AnswerHeader
()
if
err
!=
nil
&&
err
!=
dnsmessage
.
ErrSectionDone
{
if
err
!=
nil
&&
err
!=
dnsmessage
.
ErrSectionDone
{
return
&
DNSError
{
return
errCannotUnmarshalDNSMessage
Err
:
"cannot unmarshal DNS message"
,
Name
:
name
,
Server
:
server
,
}
}
}
// libresolv continues to the next server when it receives
// libresolv continues to the next server when it receives
// an invalid referral response. See golang.org/issue/15434.
// an invalid referral response. See golang.org/issue/15434.
if
h
.
RCode
==
dnsmessage
.
RCodeSuccess
&&
!
h
.
Authoritative
&&
!
h
.
RecursionAvailable
&&
err
==
dnsmessage
.
ErrSectionDone
{
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
{
if
h
.
RCode
!=
dnsmessage
.
RCodeSuccess
&&
h
.
RCode
!=
dnsmessage
.
RCodeNameError
{
...
@@ -180,11 +194,10 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string)
...
@@ -180,11 +194,10 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string)
// a name error and we didn't get success,
// a name error and we didn't get success,
// the server is behaving incorrectly or
// the server is behaving incorrectly or
// having temporary trouble.
// having temporary trouble.
err
:=
&
DNSError
{
Err
:
"server misbehaving"
,
Name
:
name
,
Server
:
server
}
if
h
.
RCode
==
dnsmessage
.
RCodeServerFailure
{
if
h
.
RCode
==
dnsmessage
.
RCodeServerFailure
{
err
.
IsTemporary
=
true
return
errServerTemporarlyMisbehaving
}
}
return
err
return
err
ServerMisbehaving
}
}
return
nil
return
nil
...
@@ -194,28 +207,16 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type, name, server stri
...
@@ -194,28 +207,16 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type, name, server stri
for
{
for
{
h
,
err
:=
p
.
AnswerHeader
()
h
,
err
:=
p
.
AnswerHeader
()
if
err
==
dnsmessage
.
ErrSectionDone
{
if
err
==
dnsmessage
.
ErrSectionDone
{
return
&
DNSError
{
return
errNoSuchHost
Err
:
errNoSuchHost
.
Error
(),
Name
:
name
,
Server
:
server
,
}
}
}
if
err
!=
nil
{
if
err
!=
nil
{
return
&
DNSError
{
return
errCannotUnmarshalDNSMessage
Err
:
"cannot unmarshal DNS message"
,
Name
:
name
,
Server
:
server
,
}
}
}
if
h
.
Type
==
qtype
{
if
h
.
Type
==
qtype
{
return
nil
return
nil
}
}
if
err
:=
p
.
SkipAnswer
();
err
!=
nil
{
if
err
:=
p
.
SkipAnswer
();
err
!=
nil
{
return
&
DNSError
{
return
errCannotUnmarshalDNSMessage
Err
:
"cannot unmarshal DNS message"
,
Name
:
name
,
Server
:
server
,
}
}
}
}
}
}
}
...
@@ -229,7 +230,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
...
@@ -229,7 +230,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
n
,
err
:=
dnsmessage
.
NewName
(
name
)
n
,
err
:=
dnsmessage
.
NewName
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
dnsmessage
.
Parser
{},
""
,
err
ors
.
New
(
"cannot marshal DNS message"
)
return
dnsmessage
.
Parser
{},
""
,
err
CannotMarshalDNSMessage
}
}
q
:=
dnsmessage
.
Question
{
q
:=
dnsmessage
.
Question
{
Name
:
n
,
Name
:
n
,
...
@@ -243,38 +244,62 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
...
@@ -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
)
p
,
h
,
err
:=
r
.
exchange
(
ctx
,
server
,
q
,
cfg
.
timeout
)
if
err
!=
nil
{
if
err
!=
nil
{
lastErr
=
&
DNSError
{
dnsErr
:
=
&
DNSError
{
Err
:
err
.
Error
(),
Err
:
err
.
Error
(),
Name
:
name
,
Name
:
name
,
Server
:
server
,
Server
:
server
,
}
}
if
nerr
,
ok
:=
err
.
(
Error
);
ok
&&
nerr
.
Timeout
()
{
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
// Set IsTemporary for socket-level errors. Note that this flag
// may also be used to indicate a SERVFAIL response.
// may also be used to indicate a SERVFAIL response.
if
_
,
ok
:=
err
.
(
*
OpError
);
ok
{
if
_
,
ok
:=
err
.
(
*
OpError
);
ok
{
lastErr
.
(
*
DNSError
)
.
IsTemporary
=
true
dnsErr
.
IsTemporary
=
true
}
}
lastErr
=
dnsErr
continue
continue
}
}
// The name does not exist, so trying another server won't help.
if
err
:=
checkHeader
(
&
p
,
h
,
name
,
server
);
err
!=
nil
{
//
dnsErr
:=
&
DNSError
{
// TODO: indicate this in a more obvious way, such as a field on DNSError?
Err
:
err
.
Error
(),
if
h
.
RCode
==
dnsmessage
.
RCodeNameError
{
Name
:
name
,
return
dnsmessage
.
Parser
{},
""
,
&
DNSError
{
Err
:
errNoSuchHost
.
Error
(),
Name
:
name
,
Server
:
server
}
Server
:
server
,
}
}
if
err
==
errServerTemporarlyMisbehaving
{
lastErr
=
checkHeader
(
&
p
,
h
,
name
,
server
)
dnsErr
.
IsTemporary
=
true
if
lastErr
!=
nil
{
}
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
continue
}
}
lastE
rr
=
skipToAnswer
(
&
p
,
qtype
,
name
,
server
)
e
rr
=
skipToAnswer
(
&
p
,
qtype
,
name
,
server
)
if
lastE
rr
==
nil
{
if
e
rr
==
nil
{
return
p
,
server
,
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
return
dnsmessage
.
Parser
{},
""
,
lastErr
...
...
libgo/go/net/dnsclient_unix_test.go
View file @
3cbb7cbb
...
@@ -1427,28 +1427,35 @@ func TestDNSGoroutineRace(t *testing.T) {
...
@@ -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
// Issue 8434: verify that Temporary returns true on an error when rcode
// is SERVFAIL
// is SERVFAIL
func
TestIssue8434
(
t
*
testing
.
T
)
{
func
TestIssue8434
(
t
*
testing
.
T
)
{
msg
:=
dnsmessage
.
Message
{
err
:=
lookupWithFake
(
fakeDNSServer
{
Header
:
dnsmessage
.
Header
{
rh
:
func
(
n
,
_
string
,
q
dnsmessage
.
Message
,
_
time
.
Time
)
(
dnsmessage
.
Message
,
error
)
{
RCode
:
dnsmessage
.
RCodeServerFailure
,
return
dnsmessage
.
Message
{
Header
:
dnsmessage
.
Header
{
ID
:
q
.
ID
,
Response
:
true
,
RCode
:
dnsmessage
.
RCodeServerFailure
,
},
Questions
:
q
.
Questions
,
},
nil
},
},
}
},
"golang.org."
,
dnsmessage
.
TypeALL
)
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"
)
if
err
==
nil
{
if
err
==
nil
{
t
.
Fatal
(
"expected an error"
)
t
.
Fatal
(
"expected an error"
)
}
}
...
@@ -1464,50 +1471,76 @@ func TestIssue8434(t *testing.T) {
...
@@ -1464,50 +1471,76 @@ func TestIssue8434(t *testing.T) {
}
}
}
}
// Issue 12778: verify that NXDOMAIN without RA bit errors as
// TestNoSuchHost verifies that tryOneName works correctly when the domain does
// "no such host" and not "server misbehaving"
// 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.
// Issue 25336: verify that NXDOMAIN errors fail fast.
func
TestIssue12778
(
t
*
testing
.
T
)
{
//
lookups
:=
0
// Issue 27525: verify that empty answers fail fast.
fake
:=
fakeDNSServer
{
func
TestNoSuchHost
(
t
*
testing
.
T
)
{
rh
:
func
(
n
,
_
string
,
q
dnsmessage
.
Message
,
_
time
.
Time
)
(
dnsmessage
.
Message
,
error
)
{
tests
:=
[]
struct
{
lookups
++
name
string
return
dnsmessage
.
Message
{
f
func
(
string
,
string
,
dnsmessage
.
Message
,
time
.
Time
)
(
dnsmessage
.
Message
,
error
)
Header
:
dnsmessage
.
Header
{
}{
ID
:
q
.
ID
,
{
Response
:
true
,
"NXDOMAIN"
,
RCode
:
dnsmessage
.
RCodeNameError
,
func
(
n
,
_
string
,
q
dnsmessage
.
Message
,
_
time
.
Time
)
(
dnsmessage
.
Message
,
error
)
{
RecursionAvailable
:
false
,
return
dnsmessage
.
Message
{
},
Header
:
dnsmessage
.
Header
{
Questions
:
q
.
Questions
,
ID
:
q
.
ID
,
},
nil
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
{
if
lookups
!=
1
{
t
.
Errorf
(
"got %d lookups, wanted 1"
,
lookups
)
t
.
Errorf
(
"got %d lookups, wanted 1"
,
lookups
)
}
}
if
err
==
nil
{
if
err
==
nil
{
t
.
Fatal
(
"expected an error"
)
t
.
Fatal
(
"expected an error"
)
}
}
de
,
ok
:=
err
.
(
*
DNSError
)
de
,
ok
:=
err
.
(
*
DNSError
)
if
!
ok
{
if
!
ok
{
t
.
Fatalf
(
"err = %#v; wanted a *net.DNSError"
,
err
)
t
.
Fatalf
(
"err = %#v; wanted a *net.DNSError"
,
err
)
}
}
if
de
.
Err
!=
errNoSuchHost
.
Error
()
{
if
de
.
Err
!=
errNoSuchHost
.
Error
()
{
t
.
Fatalf
(
"Err = %#v; wanted %q"
,
de
.
Err
,
errNoSuchHost
.
Error
())
t
.
Fatalf
(
"Err = %#v; wanted %q"
,
de
.
Err
,
errNoSuchHost
.
Error
())
}
})
}
}
}
}
...
@@ -1535,3 +1568,56 @@ func TestDNSDialTCP(t *testing.T) {
...
@@ -1535,3 +1568,56 @@ func TestDNSDialTCP(t *testing.T) {
t
.
Fatal
(
"exhange failed:"
,
err
)
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
)
}
}
libgo/go/net/http/roundtrip_js.go
View file @
3cbb7cbb
...
@@ -116,7 +116,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
...
@@ -116,7 +116,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
b
:=
result
.
Get
(
"body"
)
b
:=
result
.
Get
(
"body"
)
var
body
io
.
ReadCloser
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"
)}
body
=
&
streamReader
{
stream
:
b
.
Call
(
"getReader"
)}
}
else
{
}
else
{
// Fall back to using ArrayBuffer
// Fall back to using ArrayBuffer
...
...
libgo/go/net/lookup_unix.go
View file @
3cbb7cbb
...
@@ -299,11 +299,21 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
...
@@ -299,11 +299,21 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
Server
:
server
,
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
{
if
len
(
txts
)
==
0
{
txts
=
txt
.
TXT
txts
=
make
([]
string
,
0
,
1
)
}
else
{
txts
=
append
(
txts
,
txt
.
TXT
...
)
}
}
txts
=
append
(
txts
,
string
(
txtJoin
))
}
}
return
txts
,
nil
return
txts
,
nil
}
}
...
...
libgo/go/net/splice_test.go
View file @
3cbb7cbb
...
@@ -124,6 +124,7 @@ func testSpliceBig(t *testing.T) {
...
@@ -124,6 +124,7 @@ func testSpliceBig(t *testing.T) {
func
testSpliceHonorsLimitedReader
(
t
*
testing
.
T
)
{
func
testSpliceHonorsLimitedReader
(
t
*
testing
.
T
)
{
t
.
Run
(
"stopsAfterN"
,
testSpliceStopsAfterN
)
t
.
Run
(
"stopsAfterN"
,
testSpliceStopsAfterN
)
t
.
Run
(
"updatesN"
,
testSpliceUpdatesN
)
t
.
Run
(
"updatesN"
,
testSpliceUpdatesN
)
t
.
Run
(
"readerAtLimit"
,
testSpliceReaderAtLimit
)
}
}
func
testSpliceStopsAfterN
(
t
*
testing
.
T
)
{
func
testSpliceStopsAfterN
(
t
*
testing
.
T
)
{
...
@@ -210,7 +211,7 @@ func testSpliceUpdatesN(t *testing.T) {
...
@@ -210,7 +211,7 @@ func testSpliceUpdatesN(t *testing.T) {
}
}
}
}
func
testSpliceReaderAt
EOF
(
t
*
testing
.
T
)
{
func
testSpliceReaderAt
Limit
(
t
*
testing
.
T
)
{
clientUp
,
serverUp
,
err
:=
spliceTestSocketPair
(
"tcp"
)
clientUp
,
serverUp
,
err
:=
spliceTestSocketPair
(
"tcp"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -224,22 +225,64 @@ func testSpliceReaderAtEOF(t *testing.T) {
...
@@ -224,22 +225,64 @@ func testSpliceReaderAtEOF(t *testing.T) {
defer
clientDown
.
Close
()
defer
clientDown
.
Close
()
defer
serverDown
.
Close
()
defer
serverDown
.
Close
()
serverUp
.
Close
()
lr
:=
&
io
.
LimitedReader
{
_
,
err
,
handled
:=
splice
(
serverDown
.
(
*
TCPConn
)
.
fd
,
serverUp
)
N
:
0
,
R
:
serverUp
,
}
_
,
err
,
handled
:=
splice
(
serverDown
.
(
*
TCPConn
)
.
fd
,
lr
)
if
!
handled
{
if
!
handled
{
if
serr
,
ok
:=
err
.
(
*
os
.
SyscallError
);
ok
&&
serr
.
Syscall
==
"pipe2"
&&
serr
.
Err
==
syscall
.
ENOSYS
{
if
serr
,
ok
:=
err
.
(
*
os
.
SyscallError
);
ok
&&
serr
.
Syscall
==
"pipe2"
&&
serr
.
Err
==
syscall
.
ENOSYS
{
t
.
Skip
(
"pipe2 not supported"
)
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
)
defer
clientUp
.
Close
()
if
!
handled
{
clientDown
,
serverDown
,
err
:=
spliceTestSocketPair
(
"tcp"
)
t
.
Errorf
(
"exhausted LimitedReader: got err = %v, handled = %t, want handled = true"
,
err
,
handled
)
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
)
}
}
}
}
...
...
libgo/go/reflect/all_test.go
View file @
3cbb7cbb
...
@@ -5864,7 +5864,7 @@ func clobber() {
...
@@ -5864,7 +5864,7 @@ func clobber() {
type
funcLayoutTest
struct
{
type
funcLayoutTest
struct
{
rcvr
,
t
Type
rcvr
,
t
Type
size
,
argsize
,
retOffset
uintptr
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
gc
[]
byte
}
}
...
@@ -5886,7 +5886,7 @@ func init() {
...
@@ -5886,7 +5886,7 @@ func init() {
6
*
PtrSize
,
6
*
PtrSize
,
4
*
PtrSize
,
4
*
PtrSize
,
4
*
PtrSize
,
4
*
PtrSize
,
[]
byte
{
1
,
0
,
1
},
[]
byte
{
1
,
0
,
1
,
0
,
1
},
[]
byte
{
1
,
0
,
1
,
0
,
1
},
[]
byte
{
1
,
0
,
1
,
0
,
1
},
})
})
...
...
libgo/go/reflect/makefunc_ffi.go
View file @
3cbb7cbb
...
@@ -33,7 +33,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
...
@@ -33,7 +33,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
ap
:=
params
ap
:=
params
for
_
,
rt
:=
range
ftyp
.
in
{
for
_
,
rt
:=
range
ftyp
.
in
{
p
:=
unsafe_New
(
rt
)
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
}
v
:=
Value
{
rt
,
p
,
flag
(
rt
.
Kind
())
|
flagIndir
}
in
=
append
(
in
,
v
)
in
=
append
(
in
,
v
)
ap
=
(
unsafe
.
Pointer
)(
uintptr
(
ap
)
+
ptrSize
)
ap
=
(
unsafe
.
Pointer
)(
uintptr
(
ap
)
+
ptrSize
)
...
@@ -59,7 +59,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
...
@@ -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
)
{
if
v
.
flag
&
flagIndir
==
0
&&
(
v
.
kind
()
==
Ptr
||
v
.
kind
()
==
UnsafePointer
)
{
*
(
*
unsafe
.
Pointer
)(
addr
)
=
v
.
ptr
*
(
*
unsafe
.
Pointer
)(
addr
)
=
v
.
ptr
}
else
{
}
else
{
memmove
(
addr
,
v
.
ptr
,
typ
.
size
)
typedmemmove
(
typ
,
addr
,
v
.
ptr
)
}
}
off
+=
typ
.
size
off
+=
typ
.
size
}
}
...
...
libgo/go/reflect/value.go
View file @
3cbb7cbb
...
@@ -323,7 +323,7 @@ var callGC bool // for testing; see TestCallMethodJump
...
@@ -323,7 +323,7 @@ var callGC bool // for testing; see TestCallMethodJump
func
(
v
Value
)
call
(
op
string
,
in
[]
Value
)
[]
Value
{
func
(
v
Value
)
call
(
op
string
,
in
[]
Value
)
[]
Value
{
// Get function pointer, type.
// Get function pointer, type.
t
:=
v
.
typ
t
:=
(
*
funcType
)(
unsafe
.
Pointer
(
v
.
typ
))
var
(
var
(
fn
unsafe
.
Pointer
fn
unsafe
.
Pointer
rcvr
Value
rcvr
Value
...
@@ -472,7 +472,7 @@ func (v Value) call(op string, in []Value) []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 rcvrtype gives the method's actual receiver type.
// The return value t gives the method type signature (without the receiver).
// The return value t gives the method type signature (without the receiver).
// The return value fn is a pointer to the method code.
// The return value fn is a pointer to the method code.
func
methodReceiver
(
op
string
,
v
Value
,
methodIndex
int
)
(
rcvrtype
,
t
*
rt
ype
,
fn
unsafe
.
Pointer
)
{
func
methodReceiver
(
op
string
,
v
Value
,
methodIndex
int
)
(
rcvrtype
*
rtype
,
t
*
funcT
ype
,
fn
unsafe
.
Pointer
)
{
i
:=
methodIndex
i
:=
methodIndex
if
v
.
typ
.
Kind
()
==
Interface
{
if
v
.
typ
.
Kind
()
==
Interface
{
tt
:=
(
*
interfaceType
)(
unsafe
.
Pointer
(
v
.
typ
))
tt
:=
(
*
interfaceType
)(
unsafe
.
Pointer
(
v
.
typ
))
...
@@ -489,7 +489,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
...
@@ -489,7 +489,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
}
}
rcvrtype
=
iface
.
itab
.
typ
rcvrtype
=
iface
.
itab
.
typ
fn
=
unsafe
.
Pointer
(
&
iface
.
itab
.
fun
[
i
])
fn
=
unsafe
.
Pointer
(
&
iface
.
itab
.
fun
[
i
])
t
=
m
.
typ
t
=
(
*
funcType
)(
unsafe
.
Pointer
(
m
.
typ
))
}
else
{
}
else
{
rcvrtype
=
v
.
typ
rcvrtype
=
v
.
typ
ms
:=
v
.
typ
.
exportedMethods
()
ms
:=
v
.
typ
.
exportedMethods
()
...
@@ -501,7 +501,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
...
@@ -501,7 +501,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
panic
(
"reflect: "
+
op
+
" of unexported method"
)
panic
(
"reflect: "
+
op
+
" of unexported method"
)
}
}
fn
=
unsafe
.
Pointer
(
&
m
.
tfn
)
fn
=
unsafe
.
Pointer
(
&
m
.
tfn
)
t
=
m
.
mtyp
t
=
(
*
funcType
)(
unsafe
.
Pointer
(
m
.
mtyp
))
}
}
return
return
}
}
...
@@ -2399,10 +2399,14 @@ func mapiternext(it unsafe.Pointer)
...
@@ -2399,10 +2399,14 @@ func mapiternext(it unsafe.Pointer)
//go:noescape
//go:noescape
func
maplen
(
m
unsafe
.
Pointer
)
int
func
maplen
(
m
unsafe
.
Pointer
)
int
func
call
(
typ
*
rt
ype
,
fnaddr
unsafe
.
Pointer
,
isInterface
bool
,
isMethod
bool
,
params
*
unsafe
.
Pointer
,
results
*
unsafe
.
Pointer
)
func
call
(
typ
*
funcT
ype
,
fnaddr
unsafe
.
Pointer
,
isInterface
bool
,
isMethod
bool
,
params
*
unsafe
.
Pointer
,
results
*
unsafe
.
Pointer
)
func
ifaceE2I
(
t
*
rtype
,
src
interface
{},
dst
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.
// typedmemmove copies a value of type t to dst from src.
//go:noescape
//go:noescape
func
typedmemmove
(
t
*
rtype
,
dst
,
src
unsafe
.
Pointer
)
func
typedmemmove
(
t
*
rtype
,
dst
,
src
unsafe
.
Pointer
)
...
@@ -2412,10 +2416,6 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
...
@@ -2412,10 +2416,6 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
//go:noescape
//go:noescape
func
typedslicecopy
(
elemType
*
rtype
,
dst
,
src
sliceHeader
)
int
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,
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.
// the compiler cannot follow.
...
...
libgo/go/runtime/chan.go
View file @
3cbb7cbb
...
@@ -102,7 +102,7 @@ func makechan(t *chantype, size int) *hchan {
...
@@ -102,7 +102,7 @@ func makechan(t *chantype, size int) *hchan {
// Queue or element size is zero.
// Queue or element size is zero.
c
=
(
*
hchan
)(
mallocgc
(
hchanSize
,
nil
,
true
))
c
=
(
*
hchan
)(
mallocgc
(
hchanSize
,
nil
,
true
))
// Race detector uses this location for synchronization.
// Race detector uses this location for synchronization.
c
.
buf
=
unsafe
.
Pointer
(
c
)
c
.
buf
=
c
.
raceaddr
(
)
case
elem
.
kind
&
kindNoPointers
!=
0
:
case
elem
.
kind
&
kindNoPointers
!=
0
:
// Elements do not contain pointers.
// Elements do not contain pointers.
// Allocate hchan and buf in one call.
// Allocate hchan and buf in one call.
...
@@ -166,7 +166,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
...
@@ -166,7 +166,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
}
}
if
raceenabled
{
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.
// Fast path: check for failed non-blocking operation without acquiring the lock.
...
@@ -352,8 +352,8 @@ func closechan(c *hchan) {
...
@@ -352,8 +352,8 @@ func closechan(c *hchan) {
if
raceenabled
{
if
raceenabled
{
callerpc
:=
getcallerpc
()
callerpc
:=
getcallerpc
()
racewritepc
(
unsafe
.
Pointer
(
c
),
callerpc
,
funcPC
(
closechan
))
racewritepc
(
c
.
raceaddr
(
),
callerpc
,
funcPC
(
closechan
))
racerelease
(
unsafe
.
Pointer
(
c
))
racerelease
(
c
.
raceaddr
(
))
}
}
c
.
closed
=
1
c
.
closed
=
1
...
@@ -376,7 +376,7 @@ func closechan(c *hchan) {
...
@@ -376,7 +376,7 @@ func closechan(c *hchan) {
gp
:=
sg
.
g
gp
:=
sg
.
g
gp
.
param
=
nil
gp
.
param
=
nil
if
raceenabled
{
if
raceenabled
{
raceacquireg
(
gp
,
unsafe
.
Pointer
(
c
))
raceacquireg
(
gp
,
c
.
raceaddr
(
))
}
}
gp
.
schedlink
.
set
(
glist
)
gp
.
schedlink
.
set
(
glist
)
glist
=
gp
glist
=
gp
...
@@ -395,7 +395,7 @@ func closechan(c *hchan) {
...
@@ -395,7 +395,7 @@ func closechan(c *hchan) {
gp
:=
sg
.
g
gp
:=
sg
.
g
gp
.
param
=
nil
gp
.
param
=
nil
if
raceenabled
{
if
raceenabled
{
raceacquireg
(
gp
,
unsafe
.
Pointer
(
c
))
raceacquireg
(
gp
,
c
.
raceaddr
(
))
}
}
gp
.
schedlink
.
set
(
glist
)
gp
.
schedlink
.
set
(
glist
)
glist
=
gp
glist
=
gp
...
@@ -477,7 +477,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
...
@@ -477,7 +477,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
if
c
.
closed
!=
0
&&
c
.
qcount
==
0
{
if
c
.
closed
!=
0
&&
c
.
qcount
==
0
{
if
raceenabled
{
if
raceenabled
{
raceacquire
(
unsafe
.
Pointer
(
c
))
raceacquire
(
c
.
raceaddr
(
))
}
}
unlock
(
&
c
.
lock
)
unlock
(
&
c
.
lock
)
if
ep
!=
nil
{
if
ep
!=
nil
{
...
@@ -755,6 +755,15 @@ func (q *waitq) dequeue() *sudog {
...
@@ -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
)
{
func
racesync
(
c
*
hchan
,
sg
*
sudog
)
{
racerelease
(
chanbuf
(
c
,
0
))
racerelease
(
chanbuf
(
c
,
0
))
raceacquireg
(
sg
.
g
,
chanbuf
(
c
,
0
))
raceacquireg
(
sg
.
g
,
chanbuf
(
c
,
0
))
...
...
libgo/go/runtime/mbarrier.go
View file @
3cbb7cbb
...
@@ -309,6 +309,19 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
...
@@ -309,6 +309,19 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
memclrNoHeapPointers
(
ptr
,
typ
.
size
)
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.
// memclrHasPointers clears n bytes of typed memory starting at ptr.
// The caller must ensure that the type of the object at ptr has
// The caller must ensure that the type of the object at ptr has
// pointers, usually by checking typ.kind&kindNoPointers. However, ptr
// pointers, usually by checking typ.kind&kindNoPointers. However, ptr
...
...
libgo/go/runtime/os_darwin.go
View file @
3cbb7cbb
...
@@ -34,6 +34,10 @@ func semacreate(mp *m) {
...
@@ -34,6 +34,10 @@ func semacreate(mp *m) {
//go:nosplit
//go:nosplit
func
semasleep
(
ns
int64
)
int32
{
func
semasleep
(
ns
int64
)
int32
{
var
start
int64
if
ns
>=
0
{
start
=
nanotime
()
}
mp
:=
getg
()
.
m
mp
:=
getg
()
.
m
pthread_mutex_lock
(
&
mp
.
mutex
)
pthread_mutex_lock
(
&
mp
.
mutex
)
for
{
for
{
...
@@ -43,8 +47,13 @@ func semasleep(ns int64) int32 {
...
@@ -43,8 +47,13 @@ func semasleep(ns int64) int32 {
return
0
return
0
}
}
if
ns
>=
0
{
if
ns
>=
0
{
spent
:=
nanotime
()
-
start
if
spent
>=
ns
{
pthread_mutex_unlock
(
&
mp
.
mutex
)
return
-
1
}
var
t
timespec
var
t
timespec
t
.
set_nsec
(
ns
)
t
.
set_nsec
(
ns
-
spent
)
err
:=
pthread_cond_timedwait_relative_np
(
&
mp
.
cond
,
&
mp
.
mutex
,
&
t
)
err
:=
pthread_cond_timedwait_relative_np
(
&
mp
.
cond
,
&
mp
.
mutex
,
&
t
)
if
err
==
_ETIMEDOUT
{
if
err
==
_ETIMEDOUT
{
pthread_mutex_unlock
(
&
mp
.
mutex
)
pthread_mutex_unlock
(
&
mp
.
mutex
)
...
...
libgo/go/runtime/os_netbsd.go
View file @
3cbb7cbb
...
@@ -29,15 +29,9 @@ func semacreate(mp *m) {
...
@@ -29,15 +29,9 @@ func semacreate(mp *m) {
//go:nosplit
//go:nosplit
func
semasleep
(
ns
int64
)
int32
{
func
semasleep
(
ns
int64
)
int32
{
_g_
:=
getg
()
_g_
:=
getg
()
var
deadline
int64
// Compute sleep deadline.
var
tsp
*
timespec
var
ts
timespec
if
ns
>=
0
{
if
ns
>=
0
{
var
nsec
int32
deadline
=
nanotime
()
+
ns
ts
.
set_sec
(
int64
(
timediv
(
ns
,
1000000000
,
&
nsec
)))
ts
.
set_nsec
(
nsec
)
tsp
=
&
ts
}
}
for
{
for
{
...
@@ -50,18 +44,21 @@ func semasleep(ns int64) int32 {
...
@@ -50,18 +44,21 @@ func semasleep(ns int64) int32 {
}
}
// Sleep until unparked by semawakeup or timeout.
// 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
)
ret
:=
lwp_park
(
_CLOCK_MONOTONIC
,
_TIMER_RELTIME
,
tsp
,
0
,
unsafe
.
Pointer
(
&
_g_
.
m
.
waitsemacount
),
nil
)
if
ret
==
_ETIMEDOUT
{
if
ret
==
_ETIMEDOUT
{
return
-
1
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
)
}
}
}
}
}
}
...
...
libgo/go/runtime/select.go
View file @
3cbb7cbb
...
@@ -426,7 +426,7 @@ rclose:
...
@@ -426,7 +426,7 @@ rclose:
typedmemclr
(
c
.
elemtype
,
cas
.
elem
)
typedmemclr
(
c
.
elemtype
,
cas
.
elem
)
}
}
if
raceenabled
{
if
raceenabled
{
raceacquire
(
unsafe
.
Pointer
(
c
))
raceacquire
(
c
.
raceaddr
(
))
}
}
goto
retc
goto
retc
...
...
libgo/go/runtime/trace/annotation.go
View file @
3cbb7cbb
...
@@ -24,13 +24,13 @@ type traceContextKey struct{}
...
@@ -24,13 +24,13 @@ type traceContextKey struct{}
// If the end function is called multiple times, only the first
// If the end function is called multiple times, only the first
// call is used in the latency measurement.
// call is used in the latency measurement.
//
//
// ctx, task := trace.NewTask(ctx, "awesome
t
ask")
// ctx, task := trace.NewTask(ctx, "awesome
T
ask")
// trace.WithRegion(ctx, prepWork)
// trace.WithRegion(ctx,
"preparation",
prepWork)
// // preparation of the task
// // preparation of the task
// go func() { // continue processing the task in a separate goroutine.
// go func() { // continue processing the task in a separate goroutine.
// defer task.End()
// defer task.End()
// trace.WithRegion(ctx, remainingWork)
// trace.WithRegion(ctx,
"remainingWork",
remainingWork)
// }
// }
()
func
NewTask
(
pctx
context
.
Context
,
taskType
string
)
(
ctx
context
.
Context
,
task
*
Task
)
{
func
NewTask
(
pctx
context
.
Context
,
taskType
string
)
(
ctx
context
.
Context
,
task
*
Task
)
{
pid
:=
fromContext
(
pctx
)
.
id
pid
:=
fromContext
(
pctx
)
.
id
id
:=
newID
()
id
:=
newID
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment