| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6bb2b5a commit 0b3c80c
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2060,10 +2060,9 @@ int Http2Stream::DoWrite(WriteWrap* req_wrap, | |||
| 2060 | 2060 | uv_buf_t* bufs, | |
| 2061 | 2061 | size_t nbufs, | |
| 2062 | 2062 | uv_stream_t* send_handle) { | |
| 2063 | - CHECK(!this->IsDestroyed()); | ||
| 2064 | 2063 | CHECK_NULL(send_handle); | |
| 2065 | 2064 | Http2Scope h2scope(this); | |
| 2066 | - if (!IsWritable()) { | ||
| 2065 | + if (!IsWritable() || IsDestroyed()) { | ||
| 2067 | 2066 | req_wrap->Done(UV_EOF); | |
| 2068 | 2067 | return 0; | |
| 2069 | 2068 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -57,9 +57,11 @@ void StreamPipe::Unpipe() { | |||
| 57 | 57 | if (is_closed_) | |
| 58 | 58 | return; | |
| 59 | 59 | ||
| 60 | - // Note that we cannot use virtual methods on `source` and `sink` here, | ||
| 61 | - // because this function can be called from their destructors via | ||
| 60 | + // Note that we possibly cannot use virtual methods on `source` and `sink` | ||
| 61 | + // here, because this function can be called from their destructors via | ||
| 62 | 62 | // `OnStreamDestroy()`. | |
| 63 | + if (!source_destroyed_) | ||
| 64 | + source()->ReadStop(); | ||
| 63 | 65 | ||
| 64 | 66 | is_closed_ = true; | |
| 65 | 67 | is_reading_ = false; | |
@@ -144,7 +146,8 @@ void StreamPipe::ProcessData(size_t nread, const uv_buf_t& buf) { | |||
| 144 | 146 | is_writing_ = true; | |
| 145 | 147 | is_reading_ = false; | |
| 146 | 148 | res.wrap->SetAllocatedStorage(buf.base, buf.len); | |
| 147 | - source()->ReadStop(); | ||
| 149 | + if (source() != nullptr) | ||
| 150 | + source()->ReadStop(); | ||
| 148 | 151 | } | |
| 149 | 152 | } | |
| 150 | 153 | ||
@@ -183,13 +186,15 @@ void StreamPipe::WritableListener::OnStreamAfterShutdown(ShutdownWrap* w, | |||
| 183 | 186 | ||
| 184 | 187 | void StreamPipe::ReadableListener::OnStreamDestroy() { | |
| 185 | 188 | StreamPipe* pipe = ContainerOf(&StreamPipe::readable_listener_, this); | |
| 189 | + pipe->source_destroyed_ = true; | ||
| 186 | 190 | if (!pipe->is_eof_) { | |
| 187 | 191 | OnStreamRead(UV_EPIPE, uv_buf_init(nullptr, 0)); | |
| 188 | 192 | } | |
| 189 | 193 | } | |
| 190 | 194 | ||
| 191 | 195 | void StreamPipe::WritableListener::OnStreamDestroy() { | |
| 192 | 196 | StreamPipe* pipe = ContainerOf(&StreamPipe::writable_listener_, this); | |
| 197 | + pipe->sink_destroyed_ = true; | ||
| 193 | 198 | pipe->is_eof_ = true; | |
| 194 | 199 | pipe->Unpipe(); | |
| 195 | 200 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,16 +23,18 @@ class StreamPipe : public AsyncWrap { | |||
| 23 | 23 | } | |
| 24 | 24 | ||
| 25 | 25 | private: | |
| 26 | - StreamBase* source(); | ||
| 27 | - StreamBase* sink(); | ||
| 26 | + inline StreamBase* source(); | ||
| 27 | + inline StreamBase* sink(); | ||
| 28 | 28 | ||
| 29 | - void ShutdownWritable(); | ||
| 30 | - void FlushToWritable(); | ||
| 29 | + inline void ShutdownWritable(); | ||
| 30 | + inline void FlushToWritable(); | ||
| 31 | 31 | ||
| 32 | 32 | bool is_reading_ = false; | |
| 33 | 33 | bool is_writing_ = false; | |
| 34 | 34 | bool is_eof_ = false; | |
| 35 | 35 | bool is_closed_ = true; | |
| 36 | + bool sink_destroyed_ = false; | ||
| 37 | + bool source_destroyed_ = false; | ||
| 36 | 38 | ||
| 37 | 39 | // Set a default value so that when we’re coming from Start(), we know | |
| 38 | 40 | // that we don’t want to read just yet. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,37 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common'); | ||
| 4 | + if (!common.hasCrypto) | ||
| 5 | + common.skip('missing crypto'); | ||
| 6 | + const http2 = require('http2'); | ||
| 7 | + const net = require('net'); | ||
| 8 | + | ||
| 9 | + const { | ||
| 10 | + HTTP2_HEADER_CONTENT_TYPE | ||
| 11 | + } = http2.constants; | ||
| 12 | + | ||
| 13 | + const server = http2.createServer(); | ||
| 14 | + server.on('stream', common.mustCall((stream) => { | ||
| 15 | + stream.respondWithFile(process.execPath, { | ||
| 16 | + [HTTP2_HEADER_CONTENT_TYPE]: 'application/octet-stream' | ||
| 17 | + }); | ||
| 18 | + })); | ||
| 19 | + | ||
| 20 | + server.listen(0, common.mustCall(() => { | ||
| 21 | + const client = http2.connect(`http://localhost:${server.address().port}`); | ||
| 22 | + const req = client.request(); | ||
| 23 | + | ||
| 24 | + req.on('response', common.mustCall(() => {})); | ||
| 25 | + req.on('data', common.mustCall(() => { | ||
| 26 | + net.Socket.prototype.destroy.call(client.socket); | ||
| 27 | + server.close(); | ||
| 28 | + })); | ||
| 29 | + req.end(); | ||
| 30 | + })); | ||
| 31 | + | ||
| 32 | + // TODO(addaleax): This is a *hack*. HTTP/2 needs to have a proper way of | ||
| 33 | + // dealing with this kind of issue. | ||
| 34 | + process.once('uncaughtException', (err) => { | ||
| 35 | + if (err.code === 'ECONNRESET') return; | ||
| 36 | + throw err; | ||
| 37 | + }); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments