You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
pipeline in 13 seems to destroy duplex streams before the get a change to finish their writable flus h (ws.end() -> ws._final) lifecycle.
I managed to boil it down to a pretty straightforward test case below
conststream=require('stream')// duplex stream similar to a tcp stream etcconstdup=newstream.Duplex({write(data,enc,cb){cb()},destroy(){console.log('ws: am getting destroyed')},final(cb){console.log('ws: flushing writable...')setTimeout(function(){console.log('ws: done flushing writable...')cb()},1000)}})// just some sinkconstsink=newstream.Writable({write(data,enc,cb){cb()}})// pipe readable sidestream.pipeline(dup,sink,function(){})dup.write('test')dup.end()
Notice that the dup stream gets destroyed before it has a chance to finish it's writable flush in the _final lifecycle, due to the pipeline auto destroying it in 13.
constnet=require('net')constpipeline=require('stream').pipelinenet.createServer(function(socket){// echo serverpipeline(socket,socket,()=>{})// 13 force destroys the socket before it has a chance to emit finishsocket.on('finish',function(){console.log('finished only printed in node 12')})}).listen(10000,function(){constsocket=net.connect(10000)socket.end()})
This is a problem on v13 only as far as I can tell. Basically pre v14 net.Socket had a bit strange semantics regarding writable/readable which kind of short-circuits the writable/readable check which pipeline depends on.
This happens in master on all streams that don't have autoDestroy enabled as well (ie any readable-stream stream or any stream that opt out)
conststream=require('stream')// duplex stream similar to a tcp stream etcconstdup=newstream.Duplex({autoDestroy: false,write(data,enc,cb){cb()},read(){this.push(null)},destroy(){console.log('ws: am getting destroyed')},final(cb){console.log('ws: flushing writable...')setTimeout(function(){console.log('ws: done flushing writable...')cb()},1000)}})// just some sinkconstsink=newstream.Writable({write(data,enc,cb){cb()}})// pipe readable sidestream.pipeline(dup,sink,function(){})dup.write('test')dup.end()
Activity
mafintosh commentedon Apr 20, 2020
I think this is related to #31940 as well
mafintosh commentedon Apr 20, 2020
Equivalent test case using TCP
mcollina commentedon Apr 20, 2020
cc @ronag
ronag commentedon Apr 21, 2020
Seems to work on master. Checking v13-staging.
ronag commentedon Apr 21, 2020
This is a problem on v13 only as far as I can tell.
Basically pre v14net.Sockethad a bit strange semantics regardingwritable/readablewhich kind of short-circuits thewritable/readablecheck which pipeline depends on.ronag commentedon Apr 21, 2020
Looking into ways to get around this.
mafintosh commentedon Apr 21, 2020
This happens in master on all streams that don't have autoDestroy enabled as well (ie any readable-stream stream or any stream that opt out)
Above prints the following
cc @ronag @mcollina
ronag commentedon Apr 21, 2020
Yes, I see the problem. Will try to prepare a PR by the end of the day. Thanks a lot @mafintosh!
mafintosh commentedon Apr 21, 2020
@ronag i think this is related to #32965
ronag commentedon Apr 21, 2020
I think it's unrelated. See comment in #32965.
stream: pipeline should only destroy un-finished streams
stream: pipeline should only destroy un-finished streams
stream: pipeline should only destroy un-finished streams