Skip to content
New issue

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

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

Already on GitHub? Sign in 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants