Skip to content

Close original standard descriptors and keep C++ streams attached - #579

Open
perfloop-agent wants to merge 1 commit into
Cpp2Rust:masterfrom
perfloop-oss:perfloop-pr-open-msy2k2kavp
Open

perfloop-agent wants to merge 1 commit into
Cpp2Rust:masterfrom
perfloop-oss:perfloop-pr-open-msy2k2kavp

Conversation

@perfloop-agent

@perfloop-agent perfloop-agent commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closing a standard descriptor in refcount output now releases the OS descriptor with that number, so open can reuse it. C++ standard streams follow the original descriptor and return I/O errors after close instead of panicking or writing to a duplicate.

  • Borrow standard registry entries; keep ownership of opened files, including files opened at 0–2.
  • Use non-owning descriptor numbers for standard C++ streams and owned files for file streams.
  • Update stream aliases and iterator rules, with generated expectations refreshed for the translator's operand captures.

Generated refcount code remains safe Rust. The registry stays thread-local and intentionally keeps its existing ub: bad fd panic policy for unregistered numbers, rather than native C's EBADF. This includes main's first close after another thread closes that standard descriptor if main's registry is still uninitialized; it is not cross-thread ownership tracking.

C++ streams still do not model sticky error flags; insertion expressions discard returned I/O errors. Application exposure and runtime performance remain unmeasured.

Testing

8 recorded checks pass with this change.

  • libcc2rs unit and doc tests
  • libcc2rs clippy
  • rules clippy
  • libcc2rs rustfmt
  • rules rustfmt
  • clang-format on changed C and C++ fixtures
  • I/O documentation Prettier
  • Scoped descriptor and C++ stream lit tests

The scoped lit selection covers 42 refcount/unsafe cases. tests/unit/fd_close_standard.c compares close/open/read and descriptor-number reuse with native C. The unsafe model's descriptor-close behavior is unchanged.

tests/unit/iostream_closed.cpp compares close(1), cout, then cerr with native C++, followed by a write to closed stderr. tests/unit/stdcopy_ostream.cpp checks owned file-stream output by reading it back. The runtime's file_stream_io test checks binary reads, writes and cloned-file lifetime.

The macOS unit/max.cpp/refcount check remains owned by target CI. Its generated-output mismatch is also present in the unchanged base's CI run.

Case and evidence


Generated by Perfloop. Human sponsor: Tomás Senart.

Signed-off-by: Perfloop Agent <agent@perfloop.ai>
Signed-off-by: Tomás Senart <ts@perfloop.ai>
@perfloop
perfloop Bot force-pushed the perfloop-pr-open-msy2k2kavp branch from 3cb5fb0 to 2a70743 Compare November 1, 2026 13:40
@nunoplopes

Copy link
Copy Markdown
Contributor

@perfloop-agent The actual fix is a bit more involved. We need to create a new Stream type to hold state. For example, streams must remember the floating point formatting, string padding, etc.
We don't (shouldn't) do everything in one PR, but we need to ensure that the newly introduced type will work for all of these use cases.

This branch has not been deployed

No deployments
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