Skip to content

Do not let the GC close a borrowed stdout#3533

Open
kdeldycke wants to merge 1 commit into
pallets:stablefrom
kdeldycke:fix-pager-stream-close
Open

Do not let the GC close a borrowed stdout#3533
kdeldycke wants to merge 1 commit into
pallets:stablefrom
kdeldycke:fix-pager-stream-close

Conversation

@kdeldycke
Copy link
Copy Markdown
Collaborator

@kdeldycke kdeldycke commented May 29, 2026

Complete the partial fix proposed in #3482 for #3449.

This PR reproduce the case highlighted in #3449 where a stream that is not managed by the pager machinery is closed by it unconditionally.

As extra bonuses:

  • replace _SkipClose with utils.KeepOpenFile
  • document KeepOpenFile
  • eliminate a dead elif isinstance(stream, t.BinaryIO) branch as non-buffered text streams can be yielded as-is

This is a follow up of #3482 which is a follow up of #3405 which is a follow up of #1572.

CC @ChrisPappalardo @AndreasBackx @craigds

@davidism
Copy link
Copy Markdown
Member

I realized there's already utils.KeepOpenFile which does all the dunder stuff. Let's get rid of _SkipClose, it's redundant. (Again noticing just how many wrappers we have.)

@davidism
Copy link
Copy Markdown
Member

There also seems to be way too many context managers and levels of indirection for the pager machinery at this point. I'm not sure how we got here, but I'd sure love to refactor and simplify it somehow.

@kdeldycke
Copy link
Copy Markdown
Collaborator Author

I realized there's already utils.KeepOpenFile which does all the dunder stuff. Let's get rid of _SkipClose, it's redundant. (Again noticing just how many wrappers we have.)

TIL. Let me play a bit with utils.KeepOpenFile to see how it works...

@kdeldycke kdeldycke changed the title Complete the "I/O operation on closed file" fix from #3482 Do not let the GC close a borrowed stdout May 29, 2026
@kdeldycke
Copy link
Copy Markdown
Collaborator Author

I realized there's already utils.KeepOpenFile which does all the dunder stuff. Let's get rid of _SkipClose, it's redundant. (Again noticing just how many wrappers we have.)

Seems to do the trick! Thanks for the hint! :)

@kdeldycke
Copy link
Copy Markdown
Collaborator Author

There also seems to be way too many context managers and levels of indirection for the pager machinery at this point. I'm not sure how we got here, but I'd sure love to refactor and simplify it somehow.

This part of Click is insane. The only thing that gives me confidence is the amount of collected cases from users that we transformed into unittests.

Complete the "I/O operation on closed file" fix from pallets#3482, and definitely addresses pallets#3449.
@kdeldycke kdeldycke force-pushed the fix-pager-stream-close branch from 72c07e8 to 8b6441f Compare May 29, 2026 14:32
@kdeldycke
Copy link
Copy Markdown
Collaborator Author

I squashed the commits, this is ready to be reviewed. I'll go down the pager rabbit hole in other PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug f:test runner feature: cli test runner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"I/O operation on closed file" error with CliRunner and echo_via_pager under 8.4

2 participants