Title: pipeline deadlock with readable tail? · Issue #40685 · nodejs/node · GitHub
Open Graph Title: pipeline deadlock with readable tail? · Issue #40685 · nodejs/node
X Title: pipeline deadlock with readable tail? · Issue #40685 · nodejs/node
Description: #40653 (comment) @lpinca feel free to edit issue and fill out with your concern. Otherwise I will dig into this at some later point. The pipeline() callback might never be called if the destination is a Transform stream that is not read....
Open Graph Description: #40653 (comment) @lpinca feel free to edit issue and fill out with your concern. Otherwise I will dig into this at some later point. The pipeline() callback might never be called if the destination...
X Description: #40653 (comment) @lpinca feel free to edit issue and fill out with your concern. Otherwise I will dig into this at some later point. The pipeline() callback might never be called if the destination...
Opengraph URL: https://github.com/nodejs/node/issues/40685
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"pipeline deadlock with readable tail?","articleBody":"https://github.com/nodejs/node/pull/40653#discussion_r739873780\r\n\r\n@lpinca feel free to edit issue and fill out with your concern. Otherwise I will dig into this at some later point.\r\n\r\n---\r\n\r\nThe `pipeline()` callback might never be called if the destination is a `Transform` stream that is not read. Here is an example.\r\n\r\n```js\r\nconst stream = require('stream');\r\n\r\nconst chunk = Buffer.alloc(1024);\r\nlet bytesRead = 0;\r\n\r\nconst readable = new stream.Readable({\r\n read() {\r\n if (bytesRead === 100 * 1024) {\r\n readable.push(null);\r\n } else {\r\n bytesRead += chunk.length;\r\n readable.push(chunk);\r\n }\r\n }\r\n});\r\n\r\nconst passThrough = new stream.PassThrough();\r\n\r\nstream.pipeline(readable, passThrough, function (err) {\r\n if (err) {\r\n throw err;\r\n }\r\n\r\n console.log('done');\r\n});\r\n```\r\n\r\nIn the callback version this is not a big issue because `pipeline()` returns the last stream, so the user could resume the returned stream.\r\n\r\n```js\r\npipeline(readable, passThrough, fn).resume();\r\n```\r\n\r\nIn the promisified variant, `pipeline()` is just a wrapper that returns a promise that is fulfilled when the callback of the callback variant is called.\r\n\r\nHowever the user could not be able to resume the returned stream because they might not have direct control on it. For example if the last entry is a generator.\r\n\r\n```js\r\nconst stream = require('stream');\r\nconst streamPromises = require('stream/promises');\r\n\r\nconst chunk = Buffer.alloc(1024);\r\nlet bytesRead = 0;\r\n\r\nconst readable = new stream.Readable({\r\n read() {\r\n if (bytesRead === 100 * 1024) {\r\n readable.push(null);\r\n } else {\r\n bytesRead += chunk.length;\r\n readable.push(chunk);\r\n }\r\n }\r\n});\r\n\r\nasync function* passThrough(source) {\r\n for await (const chunk of source) {\r\n yield chunk;\r\n }\r\n}\r\n\r\nasync function run() {\r\n await streamPromises.pipeline(readable, passThrough);\r\n}\r\n\r\nrun()\r\n .then(function () {\r\n console.log('done');\r\n })\r\n .catch(console.error);\r\n```\r\n\r\nIn this case `stream.pipeline()` returns an internal `PassThrough` proxy that the user cannot resume so the promise returned by `streamPromises.pipeline()` might never be fulfilled.\r\n\r\nA possible workaround is to resume the returned stream in the promisified variant.\r\n\r\n```diff\r\ndiff --git a/lib/stream/promises.js b/lib/stream/promises.js\r\nindex 0db01a8b20..5bbadd43c5 100644\r\n--- a/lib/stream/promises.js\r\n+++ b/lib/stream/promises.js\r\n@@ -23,13 +23,17 @@ function pipeline(...streams) {\r\n signal = options.signal;\r\n }\r\n \r\n- pl(streams, (err, value) => {\r\n+ const stream = pl(streams, (err, value) => {\r\n if (err) {\r\n reject(err);\r\n } else {\r\n resolve(value);\r\n }\r\n }, { signal });\r\n+\r\n+ if (stream.readable) {\r\n+ stream.resume();\r\n+ }\r\n });\r\n }\r\n```","author":{"url":"https://github.com/ronag","@type":"Person","name":"ronag"},"datePublished":"2021-11-01T08:43:39Z","url":"https://github.com/nodejs/node/issues/40685"}
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:fbecfe0a-a899-6b04-0770-e72323249d50 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8A44:3EED53:7DB95:A9CAA:6AED0489 |
| html-safe-nonce | 6281ff201cf1e42bef1b6ccec8c36019ebb4879481d6f78ff40fd95f24fe25b7 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4QTQ0OjNFRUQ1Mzo3REI5NTpBOUNBQTo2QUVEMDQ4OSIsInZpc2l0b3JfaWQiOiI2NjE0OTczMDIxNzk1NzE0MTg1IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 8535ba5bbf5a434be74a8ee2677ab96e304ae61e29d89ec4a3390a1bcc7875ba |
| hovercard-subject-tag | issue:1040920440 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/40685/issue_layout |
| twitter:image | https://opengraph.githubassets.com/9e1e14c44cebdf2f8994d932b587f0b2e66d8dcc98f76b58318892141d3d0891/nodejs/node/issues/40685 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/9e1e14c44cebdf2f8994d932b587f0b2e66d8dcc98f76b58318892141d3d0891/nodejs/node/issues/40685 |
| og:image:alt | #40653 (comment) @lpinca feel free to edit issue and fill out with your concern. Otherwise I will dig into this at some later point. The pipeline() callback might never be called if the destination... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | ronag |
| hostname | github.com |
| expected-hostname | github.com |
| None | 21e10c535436b2122cfb44c76dfb4af296e371850fb60de16776f8a64e5c3ed8 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 302a6d707c3288a5f951258a2fa3e926b8c8f8cf |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
| react-app-name | issues |
Links:
Viewport: width=device-width