Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix aborting Streams #3754

Merged
merged 2 commits into from
Oct 29, 2024
Merged

fix aborting Streams #3754

merged 2 commits into from
Oct 29, 2024

Conversation

epistemancering
Copy link
Contributor

This relates to...

#1711

Rationale

The simple fix to the memory issue caused a worse issue. Common patterns that involve catching AbortErrors, such as retrying slow requests, silently fail if the signal unluckily happens to be aborted during the read. A proper fix to the memory issue will likely be more involved.

Changes

revert 49e33a8

Bug Fixes

Aborting a Stream doesn't throw.

const abortController = new AbortController

;(async () => {
    const readStream = (await fetch("https://www.googleapis.com/customsearch/v1", { signal: abortController.signal })).arrayBuffer()

    setTimeout(() => {
        abortController.abort()
    })

    await readStream
})()

Status

Copy link
Member

@KhafraDev KhafraDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing a test and is replacing one issue for another. I will take a look in a few days.

@KhafraDev
Copy link
Member

I need a test case that doesn't use a third party endpoint to work on it. The case you provided doesn't abort in node or Deno, and I cannot test in browsers because of CSP.

The correct fix, afaict, is to remove the previous listener if > 1 exists (such that 1 listener always exists) or to only add a listener if there are none.

@epistemancering
Copy link
Contributor Author

import * as http from "http"

const abortStream = async () => {
    const abortController = new AbortController
    const readStream = (await fetch("http://localhost", { signal: abortController.signal })).arrayBuffer()
    abortController.abort()
    console.log(await readStream)
}

http.createServer((request, response) => {
    if (request.url?.[1]) {
        response.setHeader("content-type", "text/html")

        response.end(`<!doctypehtml>
            <html>
                <body>
                    <script>
                        (${abortStream})()
                    </script>
                </body>
            </html>
        `)
    } else {
        response.end(new Uint8Array(20000))
    }
}).listen(80, abortStream)

@KhafraDev KhafraDev merged commit afeb626 into nodejs:main Oct 29, 2024
30 of 36 checks passed
@KhafraDev
Copy link
Member

Thank you!

@github-actions github-actions bot mentioned this pull request Dec 3, 2024
This was referenced Dec 16, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants