Skip to content

fix: handle open(<&) dup mode on mocked filehandles - #424

Draft
toddr-bot wants to merge 1 commit into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-dup-mocked-handles
Draft

fix: handle open(<&) dup mode on mocked filehandles#424
toddr-bot wants to merge 1 commit into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-dup-mocked-handles

Conversation

@toddr-bot

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

Copy link
Copy Markdown
Collaborator

What

open(my $dup, "<&", $fh) now works when $fh is a mocked filehandle.

Why

Previously, dup modes (<&, >&, <&=, >&=) fell through to CORE::open, which
failed with "Bad file descriptor" because mocked handles have synthetic filenos
that don't correspond to real kernel file descriptors. Any code that dups a mocked
handle (common in IO redirection tests, logging, etc.) would crash.

How

Added early detection of dup modes in __open. When the source handle belongs to
a mocked file (found via _fh_to_file), a new tied FileHandle is created sharing
the same mock data. The duplicate inherits the source's access mode (r/w/a) and
current seek position. Non-mocked handles still fall through to CORE::open.

Testing

New t/dup_handle.t with 6 subtests covering:

  • Read dup (<&) with position inheritance
  • Write dup (>&) with shared mock data
  • Read-write dup (+< source) with mode inheritance
  • fdopen variant (<&=)
  • Scope cleanup (no leaks)
  • Close independence (closing dup doesn't affect original)

Full suite: 1592 tests pass (only pre-existing fh-ref-leak.t failure, unrelated).


Quality Report

Changes: 2 files changed, 144 insertions(+)

Code scan: clean

Tests: failed (FAILED)

Branch hygiene: clean

Generated by Kōan

open() with dup modes (<&, >&, <&=, >&=) on a mocked filehandle
fell through to CORE::open, which failed with "Bad file descriptor"
because mocked handles have synthetic filenos.

Detect dup modes in __open and, when the source handle belongs to a
mocked file, create a new tied handle that shares the same mock data.
The duplicate inherits the source handle's access mode (r/w/a) and
seek position, while maintaining an independent position pointer
afterward — matching Perl's buffered-IO dup semantics.

Non-mocked handles still fall through to CORE::open as before.
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