Uh oh!
There was an error while loading. Please reload this page.
http: invoke callback with ERR_STREAM_DESTROYED if the socket is destroyed - #36692
http: invoke callback with ERR_STREAM_DESTROYED if the socket is destroyed#36692Lxxyx wants to merge 2 commits into
Conversation
Lxxyx
commented
Jan 5, 2021
ping @ronag |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ronag
left a comment
There was a problem hiding this comment.
commit description is wrong, should be invoke callback with ERR_STREAM_DESTROYED
a758806 to
9ebd6c3CompareUh oh!
There was an error while loading. Please reload this page.
9ebd6c3 to
2c2d3c3CompareUh oh!
There was an error while loading. Please reload this page.
2c2d3c3 to
c185bc3Compare
This comment has been minimized.
This comment has been minimized.
c185bc3 to
92e2750Compare
ronag
left a comment
There was a problem hiding this comment.
I kind of think this check should live directly in .end() and .write() and not (only) in writeRaw or lot's of other side effects might apply before the check.
92e2750 to
110047eCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Lxxyx
commented
Jan 5, 2021
The There is also a small question: should we move the |
I'm unsure whether we need the check in |
I need a little time to improve the code and add unit tests, the situation is a little more complicated than expected |
110047e to
9024f44CompareLxxyx
commented
Jan 6, 2021
I think something along these lines would be good and quite close to what writable.js does: diff--gita/lib/_http_outgoing.jsb/lib/_http_outgoing.jsindex50ef063241..6e6ab8eb92100644---a/lib/_http_outgoing.js+++b/lib/_http_outgoing.js
@@ -51,10+51,6 @@ const{ Buffer }=require('buffer');constcommon=require('_http_common');constcheckIsHttpToken=common._checkIsHttpToken;constcheckInvalidHeaderChar=common._checkInvalidHeaderChar;-const{-defaultTriggerAsyncIdScope,-symbols: { async_id_symbol }-}=require('internal/async_hooks');const{codes: {ERR_HTTP_HEADERS_SENT,
@@ -689,23+685,6 @@ OutgoingMessage.prototype.write =functionwrite(chunk,encoding,callback){returnret;};-functiononError(msg,err,callback){-consttriggerAsyncId=msg.socket ? msg.socket[async_id_symbol] : undefined;-defaultTriggerAsyncIdScope(triggerAsyncId,-process.nextTick,-emitErrorNt,-msg,-err,-callback);-}--functionemitErrorNt(msg,err,callback){-callback(err);-if(typeofmsg.emit==='function'&&!msg._closed){-msg.emit('error',err);-}-}-functionwrite_(msg,chunk,encoding,callback,fromEnd){if(typeofcallback!=='function')callback=nop;
@@ -730,11+709,8 @@ functionwrite_(msg,chunk,encoding,callback,fromEnd){}if(err){-if(!msg.destroyed){-onError(msg,err,callback);-}else{-process.nextTick(callback,err);-}+process.nextTick(callback,err);+msg.destroy(err);returnfalse;}
@@ -823,31+799,37 @@ OutgoingMessage.prototype.end=functionend(chunk,encoding,callback){this.socket.cork();}-if(chunk){-if(this.finished){-onError(this,-newERR_STREAM_WRITE_AFTER_END(),-typeofcallback!=='function' ? nop : callback);-returnthis;+if(chunk!==null&&chunk!==undefined)+this.write(chunk,encoding);++leterr;+if(this.writableFinished){+err=newERR_STREAM_ALREADY_FINISHED('end');+}elseif(this.destroyed){+err=newERR_STREAM_DESTROYED('end');+}++if(typeofcallback==='function'){+if(err||this.writableFinished){+process.nextTick(callback,err);+}else{+// TODO (fix): What if error?+this.once('finish',callback);}-write_(this,chunk,encoding,null,true);-}elseif(this.finished){-if(typeofcallback==='function'){-if(!this.writableFinished){-this.on('finish',callback);-}else{-callback(newERR_STREAM_ALREADY_FINISHED('end'));-}+}++if(err){+if(this.socket){+this.socket.uncork();}returnthis;-}elseif(!this._header){+}++if(!this._header){this._contentLength=0;this._implicitHeader();}-if(typeofcallback==='function')-this.once('finish',callback);-constfinish=FunctionPrototypeBind(onFinish,undefined,this);if(this._hasBody&&this.chunkedEncoding){ |
ronag
commented
Jan 6, 2021
A little more work: diff--gita/lib/_http_outgoing.jsb/lib/_http_outgoing.jsindex50ef063241..b2b3137235100644---a/lib/_http_outgoing.js+++b/lib/_http_outgoing.js
@@ -51,10+51,6 @@ const{ Buffer }=require('buffer');constcommon=require('_http_common');constcheckIsHttpToken=common._checkIsHttpToken;constcheckInvalidHeaderChar=common._checkInvalidHeaderChar;-const{-defaultTriggerAsyncIdScope,-symbols: { async_id_symbol }-}=require('internal/async_hooks');const{codes: {ERR_HTTP_HEADERS_SENT,
@@ -689,23+685,6 @@ OutgoingMessage.prototype.write=functionwrite(chunk,encoding,callback){returnret;};-functiononError(msg,err,callback){-consttriggerAsyncId=msg.socket ? msg.socket[async_id_symbol] : undefined;-defaultTriggerAsyncIdScope(triggerAsyncId,-process.nextTick,-emitErrorNt,-msg,-err,-callback);-}--functionemitErrorNt(msg,err,callback){-callback(err);-if(typeofmsg.emit==='function'&&!msg._closed){-msg.emit('error',err);-}-}-functionwrite_(msg,chunk,encoding,callback,fromEnd){if(typeofcallback!=='function')callback=nop;
@@ -730,11+709,8 @@ functionwrite_(msg,chunk,encoding,callback,fromEnd){}if(err){-if(!msg.destroyed){-onError(msg,err,callback);-}else{-process.nextTick(callback,err);-}+process.nextTick(callback,err);+msg.destroy(err);returnfalse;}
@@ -809,13+785,13 @@ functiononFinish(outmsg){outmsg.emit('finish');}-OutgoingMessage.prototype.end=functionend(chunk,encoding,callback){+OutgoingMessage.prototype.end=functionend(chunk,encoding,cb){if(typeofchunk==='function'){-callback=chunk;+cb=chunk;chunk=null;encoding=null;}elseif(typeofencoding==='function'){-callback=encoding;+cb=encoding;encoding=null;}
@@ -823,38+799,46 @@ OutgoingMessage.prototype.end=functionend(chunk,encoding,callback){this.socket.cork();}-if(chunk){-if(this.finished){-onError(this,-newERR_STREAM_WRITE_AFTER_END(),-typeofcallback!=='function' ? nop : callback);-returnthis;+if(chunk!==null&&chunk!==undefined)+this.write(chunk,encoding);++leterr;+if(!this.finished){+if(!this._header){+this._contentLength=0;+this._implicitHeader();}-write_(this,chunk,encoding,null,true);-}elseif(this.finished){-if(typeofcallback==='function'){-if(!this.writableFinished){-this.on('finish',callback);-}else{-callback(newERR_STREAM_ALREADY_FINISHED('end'));-}++constfinish=FunctionPrototypeBind(onFinish,undefined,this);++if(this._hasBody&&this.chunkedEncoding){+this._send('0\r\n'+this._trailer+'\r\n','latin1',finish);+}else{+// Force a flush, HACK.+this._send('','latin1',finish);}-returnthis;-}elseif(!this._header){-this._contentLength=0;-this._implicitHeader();-}-if(typeofcallback==='function')-this.once('finish',callback);+this.finished=true;// aka. WritableState.ended+}elseif(this.writableFinished){+err=newERR_STREAM_ALREADY_FINISHED('end');+}elseif(this.destroyed){+err=newERR_STREAM_DESTROYED('end');+}-constfinish=FunctionPrototypeBind(onFinish,undefined,this);+if(typeofcb==='function'){+if(err||this.writableFinished){+process.nextTick(cb,err);+}else{+// TODO (fix): What if error? See kOnFinished in writable.js.+this.once('finish',cb);+}+}-if(this._hasBody&&this.chunkedEncoding){-this._send('0\r\n'+this._trailer+'\r\n','latin1',finish);-}else{-// Force a flush, HACK.-this._send('','latin1',finish);+if(err){+if(this.socket){+this.socket.uncork();+}+returnthis;}if(this.socket){
@@ -864,14+848,10 @@ OutgoingMessage.prototype.end=functionend(chunk,encoding,callback){}this[kCorked]=0;-this.finished=true;-// There is the first message on the outgoing queue, and we've sent// everything to the socket.debug('outgoing message end.');-if(this.outputData.length===0&&-this.socket&&-this.socket._httpMessage===this){+if(this.outputData.length===0&&this.socket?._httpMessage===this){this._finish();} |
Sorry if I made the scope on this task a lot bigger. But some of the question you had kind of lead to one thing and then another... let me know if you wish to collaborate on this. Basically our goal here is to make |
Lxxyx
commented
Jan 6, 2021
I wish to collaborate on this, I've learned a lot from this pull request and your guidance, and it's been a lot of fun.
Should we split it into multiple Pull Request, or just implement it in this pull request? |
Do you think you can try to apply my suggestion and see if and what test might fail? We should sort those out first. Then we need to add some new tests. Once the above is done I can take a look and make some TODO's for stuff that needs test and then you can try to make those? I'll help out if you get stuck with any. |
ronag
commented
Jan 6, 2021
I think it's easier to do it here since a lot of the changes are dependent. |
Lxxyx
commented
Jan 6, 2021
5 unit tests failed at local. Detail |
ronag
commented
Jan 6, 2021
Can you push the changes? Do you want to take a try at fixing the tests? |
9024f44 to
4ebf579CompareLxxyx
commented
Jan 6, 2021
The code has been pushed.
Yes. I would like to try fixing the tests |
4ebf579 to
bbafac6CompareLxxyx
commented
Jan 12, 2021
Lxxyx
commented
May 3, 2021
Close this Pull Request due to outdated code |
Fixes: #36673
Refs: #29227 (comment)
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes