Skip to content

fix: track IO::File handles in array to support concurrent opens - #426

Draft
toddr-bot wants to merge 1 commit into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-iofile-handle-tracking
Draft

fix: track IO::File handles in array to support concurrent opens#426
toddr-bot wants to merge 1 commit into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-iofile-handle-tracking

Conversation

@toddr-bot

@toddr-bot toddr-bot commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

What

Fix _io_file_mock_open to use the {'fhs'} array instead of the scalar {'fh'} slot for tracking open IO::File handles.

Why

Opening a second IO::File handle to the same mocked file overwrote the first handle's tracking reference, making it invisible to _fh_to_file. This broke stat(), truncate(), and any filehandle-to-path lookup on the first handle — returning EBADF instead of the file's metadata.

The {'fh'} scalar slot is also used by __opendir for directory handles. While files and directories don't collide in practice, using the same slot for two different purposes is a latent conflict.

How

Changed _io_file_mock_open from:

$mock_file->{'fh'} = $fh;
Scalar::Util::weaken( $mock_file->{'fh'} ) if ref $fh;

to the {'fhs'} array pattern already used by __open:

$mock_file->{'fhs'} //= [];
push @{ $mock_file->{'fhs'} }, $fh;
Scalar::Util::weaken( $mock_file->{'fhs'}[-1] ) if ref $fh;

Testing

  • Added 7 new assertions in t/io_file_compat.t covering multiple concurrent IO::File handles and handle lookup surviving peer close
  • Full suite: 1593 tests, zero regressions (only pre-existing fh-ref-leak.t failure)

Quality Report

Changes: 2 files changed, 44 insertions(+), 3 deletions(-)

Code scan: clean

Tests: failed (4 Failed, 94 test)

Branch hygiene: clean

Generated by Kōan

_io_file_mock_open stored each IO::File handle in the scalar {'fh'} slot,
which is also used by opendir for directory handles. Opening a second
IO::File handle to the same mock overwrote the first, making it invisible
to _fh_to_file — breaking stat(), truncate(), and any filehandle-to-path
lookup on the first handle.

Switch to the {'fhs'} array pattern already used by __open, which
supports multiple concurrent handles per mock.
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.

1 participant