Commit 78d024a5 authored by Chris Broadfoot's avatar Chris Broadfoot

all: merge master into release-branch.go1.7

7a622740 net/http: make Transport use new connection if over HTTP/2 concurrency limit
219ca602 doc: fix required OS X version inconsistency for binary downloads
26015b95 runtime: make stack 16-byte aligned for external code in _rt0_amd64_linux_lib
9fde86b0 runtime, syscall: fix kernel gettimeofday ABI change on iOS 10
3a03e877 os: check for waitid returning ENOSYS
10316757 net/http: update bundled http2 for flow control window adjustment fix
da070bed syscall: fix Gettimeofday on macOS Sierra
f135c326 runtime: initialize hash algs before typemap

Change-Id: Ie176f3db1e253d75ae8e56b16d3fd9900b37dde3
parents 09fc3cc5 7a622740
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<p> <p>
<a href="https://golang.org/dl/" target="_blank">Official binary <a href="https://golang.org/dl/" target="_blank">Official binary
distributions</a> are available for the FreeBSD (release 8-STABLE and above), distributions</a> are available for the FreeBSD (release 8-STABLE and above),
Linux, Mac OS X (10.7 and above), and Windows operating systems and Linux, Mac OS X (10.8 and above), and Windows operating systems and
the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
architectures. architectures.
</p> </p>
...@@ -49,7 +49,7 @@ If your OS or architecture is not on the list, you may be able to ...@@ -49,7 +49,7 @@ If your OS or architecture is not on the list, you may be able to
<tr><td colspan="3"><hr></td></tr> <tr><td colspan="3"><hr></td></tr>
<tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</td> <td>Debian GNU/kFreeBSD not supported</td></tr> <tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported</td></tr> <tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported</td></tr>
<tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr> <tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup> for <code>cgo</code> support</td></tr>
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr> <tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr>
</table> </table>
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"math"
"net" "net"
"net/http/httptrace" "net/http/httptrace"
"net/textproto" "net/textproto"
...@@ -403,9 +404,17 @@ func (e http2ConnectionError) Error() string { ...@@ -403,9 +404,17 @@ func (e http2ConnectionError) Error() string {
type http2StreamError struct { type http2StreamError struct {
StreamID uint32 StreamID uint32
Code http2ErrCode Code http2ErrCode
Cause error // optional additional detail
}
func http2streamError(id uint32, code http2ErrCode) http2StreamError {
return http2StreamError{StreamID: id, Code: code}
} }
func (e http2StreamError) Error() string { func (e http2StreamError) Error() string {
if e.Cause != nil {
return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
}
return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code) return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
} }
...@@ -1366,7 +1375,7 @@ func http2parseWindowUpdateFrame(fh http2FrameHeader, p []byte) (http2Frame, err ...@@ -1366,7 +1375,7 @@ func http2parseWindowUpdateFrame(fh http2FrameHeader, p []byte) (http2Frame, err
if fh.StreamID == 0 { if fh.StreamID == 0 {
return nil, http2ConnectionError(http2ErrCodeProtocol) return nil, http2ConnectionError(http2ErrCodeProtocol)
} }
return nil, http2StreamError{fh.StreamID, http2ErrCodeProtocol} return nil, http2streamError(fh.StreamID, http2ErrCodeProtocol)
} }
return &http2WindowUpdateFrame{ return &http2WindowUpdateFrame{
http2FrameHeader: fh, http2FrameHeader: fh,
...@@ -1444,7 +1453,7 @@ func http2parseHeadersFrame(fh http2FrameHeader, p []byte) (_ http2Frame, err er ...@@ -1444,7 +1453,7 @@ func http2parseHeadersFrame(fh http2FrameHeader, p []byte) (_ http2Frame, err er
} }
} }
if len(p)-int(padLength) <= 0 { if len(p)-int(padLength) <= 0 {
return nil, http2StreamError{fh.StreamID, http2ErrCodeProtocol} return nil, http2streamError(fh.StreamID, http2ErrCodeProtocol)
} }
hf.headerFragBuf = p[:len(p)-int(padLength)] hf.headerFragBuf = p[:len(p)-int(padLength)]
return hf, nil return hf, nil
...@@ -1911,6 +1920,9 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr ...@@ -1911,6 +1920,9 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr
hdec.SetEmitEnabled(true) hdec.SetEmitEnabled(true)
hdec.SetMaxStringLength(fr.maxHeaderStringLen()) hdec.SetMaxStringLength(fr.maxHeaderStringLen())
hdec.SetEmitFunc(func(hf hpack.HeaderField) { hdec.SetEmitFunc(func(hf hpack.HeaderField) {
if http2VerboseLogs && http2logFrameReads {
log.Printf("http2: decoded hpack field %+v", hf)
}
if !httplex.ValidHeaderFieldValue(hf.Value) { if !httplex.ValidHeaderFieldValue(hf.Value) {
invalid = http2headerFieldValueError(hf.Value) invalid = http2headerFieldValueError(hf.Value)
} }
...@@ -1969,11 +1981,17 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr ...@@ -1969,11 +1981,17 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr
} }
if invalid != nil { if invalid != nil {
fr.errDetail = invalid fr.errDetail = invalid
return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol} if http2VerboseLogs {
log.Printf("http2: invalid header: %v", invalid)
}
return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol, invalid}
} }
if err := mh.checkPseudos(); err != nil { if err := mh.checkPseudos(); err != nil {
fr.errDetail = err fr.errDetail = err
return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol} if http2VerboseLogs {
log.Printf("http2: invalid pseudo headers: %v", err)
}
return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol, err}
} }
return mh, nil return mh, nil
} }
...@@ -3604,7 +3622,7 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) { ...@@ -3604,7 +3622,7 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
case http2stateOpen: case http2stateOpen:
st.state = http2stateHalfClosedLocal st.state = http2stateHalfClosedLocal
errCancel := http2StreamError{st.id, http2ErrCodeCancel} errCancel := http2streamError(st.id, http2ErrCodeCancel)
sc.resetStream(errCancel) sc.resetStream(errCancel)
case http2stateHalfClosedRemote: case http2stateHalfClosedRemote:
sc.closeStream(st, http2errHandlerComplete) sc.closeStream(st, http2errHandlerComplete)
...@@ -3797,7 +3815,7 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error ...@@ -3797,7 +3815,7 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error
return nil return nil
} }
if !st.flow.add(int32(f.Increment)) { if !st.flow.add(int32(f.Increment)) {
return http2StreamError{f.StreamID, http2ErrCodeFlowControl} return http2streamError(f.StreamID, http2ErrCodeFlowControl)
} }
default: default:
if !sc.flow.add(int32(f.Increment)) { if !sc.flow.add(int32(f.Increment)) {
...@@ -3819,7 +3837,7 @@ func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error { ...@@ -3819,7 +3837,7 @@ func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error {
if st != nil { if st != nil {
st.gotReset = true st.gotReset = true
st.cancelCtx() st.cancelCtx()
sc.closeStream(st, http2StreamError{f.StreamID, f.ErrCode}) sc.closeStream(st, http2streamError(f.StreamID, f.ErrCode))
} }
return nil return nil
} }
...@@ -3922,13 +3940,13 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { ...@@ -3922,13 +3940,13 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
if !ok || st.state != http2stateOpen || st.gotTrailerHeader { if !ok || st.state != http2stateOpen || st.gotTrailerHeader {
if sc.inflow.available() < int32(f.Length) { if sc.inflow.available() < int32(f.Length) {
return http2StreamError{id, http2ErrCodeFlowControl} return http2streamError(id, http2ErrCodeFlowControl)
} }
sc.inflow.take(int32(f.Length)) sc.inflow.take(int32(f.Length))
sc.sendWindowUpdate(nil, int(f.Length)) sc.sendWindowUpdate(nil, int(f.Length))
return http2StreamError{id, http2ErrCodeStreamClosed} return http2streamError(id, http2ErrCodeStreamClosed)
} }
if st.body == nil { if st.body == nil {
panic("internal error: should have a body in this state") panic("internal error: should have a body in this state")
...@@ -3936,19 +3954,19 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error { ...@@ -3936,19 +3954,19 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes { if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes)) st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
return http2StreamError{id, http2ErrCodeStreamClosed} return http2streamError(id, http2ErrCodeStreamClosed)
} }
if f.Length > 0 { if f.Length > 0 {
if st.inflow.available() < int32(f.Length) { if st.inflow.available() < int32(f.Length) {
return http2StreamError{id, http2ErrCodeFlowControl} return http2streamError(id, http2ErrCodeFlowControl)
} }
st.inflow.take(int32(f.Length)) st.inflow.take(int32(f.Length))
if len(data) > 0 { if len(data) > 0 {
wrote, err := st.body.Write(data) wrote, err := st.body.Write(data)
if err != nil { if err != nil {
return http2StreamError{id, http2ErrCodeStreamClosed} return http2streamError(id, http2ErrCodeStreamClosed)
} }
if wrote != len(data) { if wrote != len(data) {
panic("internal error: bad Writer") panic("internal error: bad Writer")
...@@ -4046,10 +4064,10 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error { ...@@ -4046,10 +4064,10 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
if sc.unackedSettings == 0 { if sc.unackedSettings == 0 {
return http2StreamError{st.id, http2ErrCodeProtocol} return http2streamError(st.id, http2ErrCodeProtocol)
} }
return http2StreamError{st.id, http2ErrCodeRefusedStream} return http2streamError(st.id, http2ErrCodeRefusedStream)
} }
rw, req, err := sc.newWriterAndRequest(st, f) rw, req, err := sc.newWriterAndRequest(st, f)
...@@ -4083,18 +4101,18 @@ func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error { ...@@ -4083,18 +4101,18 @@ func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error {
} }
st.gotTrailerHeader = true st.gotTrailerHeader = true
if !f.StreamEnded() { if !f.StreamEnded() {
return http2StreamError{st.id, http2ErrCodeProtocol} return http2streamError(st.id, http2ErrCodeProtocol)
} }
if len(f.PseudoFields()) > 0 { if len(f.PseudoFields()) > 0 {
return http2StreamError{st.id, http2ErrCodeProtocol} return http2streamError(st.id, http2ErrCodeProtocol)
} }
if st.trailer != nil { if st.trailer != nil {
for _, hf := range f.RegularFields() { for _, hf := range f.RegularFields() {
key := sc.canonicalHeader(hf.Name) key := sc.canonicalHeader(hf.Name)
if !http2ValidTrailerHeader(key) { if !http2ValidTrailerHeader(key) {
return http2StreamError{st.id, http2ErrCodeProtocol} return http2streamError(st.id, http2ErrCodeProtocol)
} }
st.trailer[key] = append(st.trailer[key], hf.Value) st.trailer[key] = append(st.trailer[key], hf.Value)
} }
...@@ -4148,18 +4166,18 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead ...@@ -4148,18 +4166,18 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead
isConnect := method == "CONNECT" isConnect := method == "CONNECT"
if isConnect { if isConnect {
if path != "" || scheme != "" || authority == "" { if path != "" || scheme != "" || authority == "" {
return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol} return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
} }
} else if method == "" || path == "" || } else if method == "" || path == "" ||
(scheme != "https" && scheme != "http") { (scheme != "https" && scheme != "http") {
return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol} return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
} }
bodyOpen := !f.StreamEnded() bodyOpen := !f.StreamEnded()
if method == "HEAD" && bodyOpen { if method == "HEAD" && bodyOpen {
return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol} return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
} }
var tlsState *tls.ConnectionState // nil if not scheme https var tlsState *tls.ConnectionState // nil if not scheme https
...@@ -4216,7 +4234,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead ...@@ -4216,7 +4234,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead
var err error var err error
url_, err = url.ParseRequestURI(path) url_, err = url.ParseRequestURI(path)
if err != nil { if err != nil {
return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol} return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
} }
requestURI = path requestURI = path
} }
...@@ -4993,14 +5011,14 @@ type http2ClientConn struct { ...@@ -4993,14 +5011,14 @@ type http2ClientConn struct {
br *bufio.Reader br *bufio.Reader
fr *http2Framer fr *http2Framer
lastActive time.Time lastActive time.Time
// Settings from peer: (also guarded by mu)
// Settings from peer:
maxFrameSize uint32 maxFrameSize uint32
maxConcurrentStreams uint32 maxConcurrentStreams uint32
initialWindowSize uint32 initialWindowSize uint32
hbuf bytes.Buffer // HPACK encoder writes into this
henc *hpack.Encoder hbuf bytes.Buffer // HPACK encoder writes into this
freeBuf [][]byte henc *hpack.Encoder
freeBuf [][]byte
wmu sync.Mutex // held while writing; acquire AFTER mu if holding both wmu sync.Mutex // held while writing; acquire AFTER mu if holding both
werr error // first write error that has occurred werr error // first write error that has occurred
...@@ -5244,10 +5262,6 @@ func (t *http2Transport) NewClientConn(c net.Conn) (*http2ClientConn, error) { ...@@ -5244,10 +5262,6 @@ func (t *http2Transport) NewClientConn(c net.Conn) (*http2ClientConn, error) {
} }
func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2ClientConn, error) { func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2ClientConn, error) {
if http2VerboseLogs {
t.vlogf("http2: Transport creating client conn to %v", c.RemoteAddr())
}
cc := &http2ClientConn{ cc := &http2ClientConn{
t: t, t: t,
tconn: c, tconn: c,
...@@ -5260,6 +5274,10 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client ...@@ -5260,6 +5274,10 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client
singleUse: singleUse, singleUse: singleUse,
wantSettingsAck: true, wantSettingsAck: true,
} }
if http2VerboseLogs {
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
}
cc.cond = sync.NewCond(&cc.mu) cc.cond = sync.NewCond(&cc.mu)
cc.flow.add(int32(http2initialWindowSize)) cc.flow.add(int32(http2initialWindowSize))
...@@ -5324,7 +5342,7 @@ func (cc *http2ClientConn) canTakeNewRequestLocked() bool { ...@@ -5324,7 +5342,7 @@ func (cc *http2ClientConn) canTakeNewRequestLocked() bool {
} }
return cc.goAway == nil && !cc.closed && return cc.goAway == nil && !cc.closed &&
int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) && int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
cc.nextStreamID < 2147483647 cc.nextStreamID < math.MaxInt32
} }
func (cc *http2ClientConn) closeIfIdle() { func (cc *http2ClientConn) closeIfIdle() {
...@@ -5334,9 +5352,13 @@ func (cc *http2ClientConn) closeIfIdle() { ...@@ -5334,9 +5352,13 @@ func (cc *http2ClientConn) closeIfIdle() {
return return
} }
cc.closed = true cc.closed = true
nextID := cc.nextStreamID
cc.mu.Unlock() cc.mu.Unlock()
if http2VerboseLogs {
cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, nextID-2)
}
cc.tconn.Close() cc.tconn.Close()
} }
...@@ -5986,11 +6008,15 @@ func (rl *http2clientConnReadLoop) run() error { ...@@ -5986,11 +6008,15 @@ func (rl *http2clientConnReadLoop) run() error {
for { for {
f, err := cc.fr.ReadFrame() f, err := cc.fr.ReadFrame()
if err != nil { if err != nil {
cc.vlogf("Transport readFrame error: (%T) %v", err, err) cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
} }
if se, ok := err.(http2StreamError); ok { if se, ok := err.(http2StreamError); ok {
if cs := cc.streamByID(se.StreamID, true); cs != nil { if cs := cc.streamByID(se.StreamID, true); cs != nil {
rl.endStreamError(cs, cc.fr.errDetail) cs.cc.writeStreamReset(cs.ID, se.Code, err)
if se.Cause == nil {
se.Cause = cc.fr.errDetail
}
rl.endStreamError(cs, se)
} }
continue continue
} else if err != nil { } else if err != nil {
...@@ -6034,6 +6060,9 @@ func (rl *http2clientConnReadLoop) run() error { ...@@ -6034,6 +6060,9 @@ func (rl *http2clientConnReadLoop) run() error {
cc.logf("Transport: unhandled response frame type %T", f) cc.logf("Transport: unhandled response frame type %T", f)
} }
if err != nil { if err != nil {
if http2VerboseLogs {
cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, http2summarizeFrame(f), err)
}
return err return err
} }
if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
...@@ -6381,6 +6410,11 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err ...@@ -6381,6 +6410,11 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err
if http2isConnectionCloseRequest(cs.req) { if http2isConnectionCloseRequest(cs.req) {
rl.closeWhenIdle = true rl.closeWhenIdle = true
} }
select {
case cs.resc <- http2resAndError{err: err}:
default:
}
} }
func (cs *http2clientStream) copyTrailers() { func (cs *http2clientStream) copyTrailers() {
...@@ -6425,6 +6459,16 @@ func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error ...@@ -6425,6 +6459,16 @@ func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error
cc.maxConcurrentStreams = s.Val cc.maxConcurrentStreams = s.Val
case http2SettingInitialWindowSize: case http2SettingInitialWindowSize:
if s.Val > math.MaxInt32 {
return http2ConnectionError(http2ErrCodeFlowControl)
}
delta := int32(s.Val) - int32(cc.initialWindowSize)
for _, cs := range cc.streams {
cs.flow.add(delta)
}
cc.cond.Broadcast()
cc.initialWindowSize = s.Val cc.initialWindowSize = s.Val
default: default:
...@@ -6475,7 +6519,7 @@ func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) er ...@@ -6475,7 +6519,7 @@ func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) er
case <-cs.peerReset: case <-cs.peerReset:
default: default:
err := http2StreamError{cs.ID, f.ErrCode} err := http2streamError(cs.ID, f.ErrCode)
cs.resetErr = err cs.resetErr = err
close(cs.peerReset) close(cs.peerReset)
cs.bufPipe.CloseWithError(err) cs.bufPipe.CloseWithError(err)
......
...@@ -398,6 +398,15 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) { ...@@ -398,6 +398,15 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
// HTTP request on a new connection. The non-nil input error is the // HTTP request on a new connection. The non-nil input error is the
// error from roundTrip. // error from roundTrip.
func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool { func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool {
if err == http2ErrNoCachedConn {
// Issue 16582: if the user started a bunch of
// requests at once, they can all pick the same conn
// and violate the server's max concurrent streams.
// Instead, match the HTTP/1 behavior for now and dial
// again to get a new TCP connection, rather than failing
// this request.
return true
}
if err == errMissingHost { if err == errMissingHost {
// User error. // User error.
return false return false
......
...@@ -28,6 +28,12 @@ func (p *Process) blockUntilWaitable() (bool, error) { ...@@ -28,6 +28,12 @@ func (p *Process) blockUntilWaitable() (bool, error) {
_, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0) _, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0)
runtime.KeepAlive(psig) runtime.KeepAlive(psig)
if e != 0 { if e != 0 {
// waitid has been available since Linux 2.6.9, but
// reportedly is not available in Ubuntu on Windows.
// See issue 16610.
if e == syscall.ENOSYS {
return false, nil
}
return false, NewSyscallError("waitid", e) return false, NewSyscallError("waitid", e)
} }
return true, nil return true, nil
......
...@@ -289,7 +289,7 @@ var aeskeysched [hashRandomBytes]byte ...@@ -289,7 +289,7 @@ var aeskeysched [hashRandomBytes]byte
// used in hash{32,64}.go to seed the hash function // used in hash{32,64}.go to seed the hash function
var hashkey [4]uintptr var hashkey [4]uintptr
func init() { func alginit() {
// Install aes hash algorithm if we have the instructions we need // Install aes hash algorithm if we have the instructions we need
if (GOARCH == "386" || GOARCH == "amd64") && if (GOARCH == "386" || GOARCH == "amd64") &&
GOOS != "nacl" && GOOS != "nacl" &&
......
...@@ -439,7 +439,8 @@ func schedinit() { ...@@ -439,7 +439,8 @@ func schedinit() {
stackinit() stackinit()
mallocinit() mallocinit()
mcommoninit(_g_.m) mcommoninit(_g_.m)
typelinksinit() alginit() // maps must not be used before this call
typelinksinit() // uses maps
itabsinit() itabsinit()
msigsave(_g_.m) msigsave(_g_.m)
......
...@@ -12,13 +12,18 @@ TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8 ...@@ -12,13 +12,18 @@ TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
// When building with -buildmode=c-shared, this symbol is called when the shared // When building with -buildmode=c-shared, this symbol is called when the shared
// library is loaded. // library is loaded.
TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x48 // Note: This function calls external C code, which might required 16-byte stack
// alignment after cmd/internal/obj applies its transformations.
TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x50
MOVQ SP, AX
ANDQ $-16, SP
MOVQ BX, 0x10(SP) MOVQ BX, 0x10(SP)
MOVQ BP, 0x18(SP) MOVQ BP, 0x18(SP)
MOVQ R12, 0x20(SP) MOVQ R12, 0x20(SP)
MOVQ R13, 0x28(SP) MOVQ R13, 0x28(SP)
MOVQ R14, 0x30(SP) MOVQ R14, 0x30(SP)
MOVQ R15, 0x38(SP) MOVQ R15, 0x38(SP)
MOVQ AX, 0x40(SP)
MOVQ DI, _rt0_amd64_linux_lib_argc<>(SB) MOVQ DI, _rt0_amd64_linux_lib_argc<>(SB)
MOVQ SI, _rt0_amd64_linux_lib_argv<>(SB) MOVQ SI, _rt0_amd64_linux_lib_argv<>(SB)
...@@ -50,6 +55,7 @@ restore: ...@@ -50,6 +55,7 @@ restore:
MOVQ 0x28(SP), R13 MOVQ 0x28(SP), R13
MOVQ 0x30(SP), R14 MOVQ 0x30(SP), R14
MOVQ 0x38(SP), R15 MOVQ 0x38(SP), R15
MOVQ 0x40(SP), SP
RET RET
TEXT _rt0_amd64_linux_lib_go(SB),NOSPLIT,$0 TEXT _rt0_amd64_linux_lib_go(SB),NOSPLIT,$0
......
...@@ -162,11 +162,15 @@ TEXT runtime·mincore(SB),NOSPLIT,$0 ...@@ -162,11 +162,15 @@ TEXT runtime·mincore(SB),NOSPLIT,$0
TEXT time·now(SB), 7, $32 TEXT time·now(SB), 7, $32
MOVW $8(R13), R0 // timeval MOVW $8(R13), R0 // timeval
MOVW $0, R1 // zone MOVW $0, R1 // zone
MOVW $0, R2 // see issue 16570
MOVW $SYS_gettimeofday, R12 MOVW $SYS_gettimeofday, R12
SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec
CMP $0, R0
BNE inreg
MOVW 8(R13), R0
MOVW 12(R13), R1
inreg:
MOVW R1, R2 // usec MOVW R1, R2 // usec
MOVW R0, sec+0(FP) MOVW R0, sec+0(FP)
MOVW $0, R1 MOVW $0, R1
MOVW R1, loc+4(FP) MOVW R1, loc+4(FP)
...@@ -178,9 +182,14 @@ TEXT time·now(SB), 7, $32 ...@@ -178,9 +182,14 @@ TEXT time·now(SB), 7, $32
TEXT runtime·nanotime(SB),NOSPLIT,$32 TEXT runtime·nanotime(SB),NOSPLIT,$32
MOVW $8(R13), R0 // timeval MOVW $8(R13), R0 // timeval
MOVW $0, R1 // zone MOVW $0, R1 // zone
MOVW $0, R2 // see issue 16570
MOVW $SYS_gettimeofday, R12 MOVW $SYS_gettimeofday, R12
SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec SWI $0x80 // Note: R0 is tv_sec, R1 is tv_usec
CMP $0, R0
BNE inreg
MOVW 8(R13), R0
MOVW 12(R13), R1
inreg:
MOVW R1, R2 MOVW R1, R2
MOVW $1000000000, R3 MOVW $1000000000, R3
MULLU R0, R3, (R1, R0) MULLU R0, R3, (R1, R0)
......
...@@ -155,9 +155,14 @@ TEXT time·now(SB),NOSPLIT,$40-12 ...@@ -155,9 +155,14 @@ TEXT time·now(SB),NOSPLIT,$40-12
MOVD RSP, R0 // timeval MOVD RSP, R0 // timeval
MOVD R0, R9 // this is how dyld calls gettimeofday MOVD R0, R9 // this is how dyld calls gettimeofday
MOVW $0, R1 // zone MOVW $0, R1 // zone
MOVD $0, R2 // see issue 16570
MOVW $SYS_gettimeofday, R16 MOVW $SYS_gettimeofday, R16
SVC $0x80 // Note: x0 is tv_sec, w1 is tv_usec SVC $0x80 // Note: x0 is tv_sec, w1 is tv_usec
CMP $0, R0
BNE inreg
MOVD 0(RSP), R0
MOVW 8(RSP), R1
inreg:
MOVD R0, sec+0(FP) MOVD R0, sec+0(FP)
MOVW $1000, R3 MOVW $1000, R3
MUL R3, R1 MUL R3, R1
...@@ -168,9 +173,14 @@ TEXT runtime·nanotime(SB),NOSPLIT,$40 ...@@ -168,9 +173,14 @@ TEXT runtime·nanotime(SB),NOSPLIT,$40
MOVD RSP, R0 // timeval MOVD RSP, R0 // timeval
MOVD R0, R9 // this is how dyld calls gettimeofday MOVD R0, R9 // this is how dyld calls gettimeofday
MOVW $0, R1 // zone MOVW $0, R1 // zone
MOVD $0, R2 // see issue 16570
MOVW $SYS_gettimeofday, R16 MOVW $SYS_gettimeofday, R16
SVC $0x80 // Note: x0 is tv_sec, w1 is tv_usec SVC $0x80 // Note: x0 is tv_sec, w1 is tv_usec
CMP $0, R0
BNE inreg
MOVD 0(RSP), R0
MOVW 8(RSP), R1
inreg:
MOVW $1000000000, R3 MOVW $1000000000, R3
MUL R3, R0 MUL R3, R0
MOVW $1000, R3 MOVW $1000, R3
......
...@@ -26,14 +26,21 @@ func NsecToTimeval(nsec int64) (tv Timeval) { ...@@ -26,14 +26,21 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
} }
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error) //sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) { func Gettimeofday(tv *Timeval) error {
// The tv passed to gettimeofday must be non-nil // The tv passed to gettimeofday must be non-nil.
// but is otherwise unused. The answers come back // Before macOS Sierra (10.12), tv was otherwise unused and
// in the two registers. // the answers came back in the two registers.
// As of Sierra, gettimeofday return zeros and populates
// tv itself.
sec, usec, err := gettimeofday(tv) sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec) if err != nil {
tv.Usec = int32(usec) return err
return err }
if sec != 0 || usec != 0 {
tv.Sec = int32(sec)
tv.Usec = int32(usec)
}
return nil
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
......
...@@ -26,14 +26,21 @@ func NsecToTimeval(nsec int64) (tv Timeval) { ...@@ -26,14 +26,21 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
} }
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error) //sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) { func Gettimeofday(tv *Timeval) error {
// The tv passed to gettimeofday must be non-nil // The tv passed to gettimeofday must be non-nil.
// but is otherwise unused. The answers come back // Before macOS Sierra (10.12), tv was otherwise unused and
// in the two registers. // the answers came back in the two registers.
// As of Sierra, gettimeofday return zeros and populates
// tv itself.
sec, usec, err := gettimeofday(tv) sec, usec, err := gettimeofday(tv)
tv.Sec = sec if err != nil {
tv.Usec = usec return err
return err }
if sec != 0 || usec != 0 {
tv.Sec = sec
tv.Usec = usec
}
return nil
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
......
...@@ -26,14 +26,19 @@ func NsecToTimeval(nsec int64) (tv Timeval) { ...@@ -26,14 +26,19 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
} }
//sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error) //sysnb gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) { func Gettimeofday(tv *Timeval) error {
// The tv passed to gettimeofday must be non-nil // The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back // but is otherwise unused. The answers come back
// in the two registers. // in the two registers.
sec, usec, err := gettimeofday(tv) sec, usec, err := gettimeofday(tv)
tv.Sec = int32(sec) if err != nil {
tv.Usec = int32(usec) return err
return err }
if sec != 0 || usec != 0 {
tv.Sec = int32(sec)
tv.Usec = int32(usec)
}
return nil
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
......
...@@ -26,14 +26,19 @@ func NsecToTimeval(nsec int64) (tv Timeval) { ...@@ -26,14 +26,19 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
} }
//sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error) //sysnb gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
func Gettimeofday(tv *Timeval) (err error) { func Gettimeofday(tv *Timeval) error {
// The tv passed to gettimeofday must be non-nil // The tv passed to gettimeofday must be non-nil
// but is otherwise unused. The answers come back // but is otherwise unused. The answers come back
// in the two registers. // in the two registers.
sec, usec, err := gettimeofday(tv) sec, usec, err := gettimeofday(tv)
tv.Sec = sec if err != nil {
tv.Usec = usec return err
return err }
if sec != 0 || usec != 0 {
tv.Sec = sec
tv.Usec = usec
}
return nil
} }
func SetKevent(k *Kevent_t, fd, mode, flags int) { func SetKevent(k *Kevent_t, fd, mode, flags int) {
......
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin
// +build amd64 386 arm arm64
package syscall_test
import (
"syscall"
"testing"
)
func TestDarwinGettimeofday(t *testing.T) {
tv := &syscall.Timeval{}
if err := syscall.Gettimeofday(tv); err != nil {
t.Fatal(err)
}
if tv.Sec == 0 && tv.Usec == 0 {
t.Fatal("Sec and Usec both zero")
}
}
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