Skip to content

Fix standard-stream inheritance and platform log chunking - #236

Open
bkaradzic-microsoft wants to merge 3 commits into
mainfrom
fix/standard-stream-logger-followups
Open

bkaradzic-microsoft wants to merge 3 commits into
mainfrom
fix/standard-stream-logger-followups

Conversation

@bkaradzic-microsoft

@bkaradzic-microsoft bkaradzic-microsoft commented Sep 10, 2026

Copy link
Copy Markdown
Member

Follow-up to #233, addressing Gary's original review and the follow-up review.

Changes

  • Make persistent private saved/reader descriptors non-inheritable: F_DUPFD_CLOEXEC on POSIX; non-inheritable DuplicateHandle plus _open_osfhandle(_O_BINARY | _O_NOINHERIT) on Windows, excluding private entries from CRT _spawn* serialization as well as kernel inheritance.
  • Use pipe2(O_CLOEXEC) on Android. Keep the checked pipe/fcntl fallback on Apple, which has no pipe2.
  • Save and restore target inheritance flags during redirection, Stop, and rollback. Preserve Windows standard-handle behavior, including unavailable GUI descriptors (_get_osfhandle returning -2).
  • Preserve Windows CRT translation modes for targets with valid handles during active redirection and restoration. Tee already-translated bytes through binary private descriptors, without a second translation. Decode UTF-16 only for platform diagnostics, retaining incomplete code units/surrogate pairs between reads and replacing malformed input.
  • Enforce byte limits for complete and unterminated lines: 3,800 bytes on Windows/Android, 1,023 bytes for Apple default output, and 255 bytes for Apple error output. Preserve UTF-8 boundaries, CRLF, and intentional blank lines; platform chunking does not alter original tee bytes.
  • Add lifecycle, byte-preservation, line-boundary, UTF-8/UTF-16, POSIX flag, Windows mode/restoration, and CRT child-startup metadata regressions. Windows child probes run before GTest initialization and are excluded from UWP.

Windows CRT-state limitation

CRT append semantics are not preserved. Private Windows descriptors are reconstructed as binary, non-inheritable descriptors. Translation modes are restored explicitly, but other CRT-only flags, including _O_APPEND, are not retained in those private copies or restored targets. This affects both tee writes and writes after Stop(); applications requiring CRT append semantics must not use Windows forwarding. This replaces the previous description's overly broad claim of full CRT-state preservation.

Process-creation limitation

Applications must serialize child-process creation with Start()/Stop(). Apple's pipe/fcntl fallback, Windows' short-lived CRT mode probe, and descriptor replacement followed by inheritance-flag restoration cannot be atomic with child creation. Persistent private descriptors are non-inheritable while forwarding is active.

Validation

  • Windows x64 QuickJS RelWithDebInfo: 16/16 focused logger tests passed across three shuffled runs.
  • Both new Windows regressions fail against the previous head, 9b44d12: active modes become binary, and private descriptors are serialized in CRT child-startup metadata.
  • CI for 04b808f546cca3256d3b03f886329ad5dc891041 is fully green: 25/25 checks passed (run 35155569100, attempt 2). The initial Android QuickJS failure was an Android Platform 33 SDK archive installation error before compilation; the retry passed without source changes.

Copilot AI lite review requested due to automatic review settings September 10, 2026 22:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Gate or explicitly enable the pipe2 feature declaration for the desktop POSIX test target.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates standard-stream redirection to prevent descriptor inheritance and adds platform-specific diagnostic log chunking with regression coverage.

Changes:

  • Preserves descriptor flags while enforcing non-inheritance.
  • Adds bounded, UTF-8-aware platform log chunking.
  • Expands lifecycle, descriptor, and chunking tests.
File summaries
File Summary
Tests/UnitTests/Shared/StandardStreamLoggerPosix.cpp POSIX descriptor tests
Tests/UnitTests/Shared/StandardStreamLoggerLines.cpp Chunking and UTF-8 tests
Tests/UnitTests/Shared/StandardStreamLogger.cpp Lifecycle and preservation tests
Tests/UnitTests/CMakeLists.txt Desktop test registration
Tests/UnitTests/Android/app/src/main/cpp/CMakeLists.txt Android test registration
Core/Foundation/Source/StandardStreamLoggerLines.h Bounded line processing
Core/Foundation/Source/StandardStreamLogger_Windows.cpp Windows inheritance handling
Core/Foundation/Source/StandardStreamLogger_Shared.inl Shared draining and chunk emission
Core/Foundation/Source/StandardStreamLogger_PosixOps.inl POSIX descriptor and pipe handling
Core/Foundation/Source/StandardStreamLogger_Apple.cpp Apple log limits
Core/Foundation/Source/StandardStreamLogger_Android.cpp Android log limits
Core/Foundation/Include/Babylon/StandardStreamLogger.h API documentation
Core/Foundation/CMakeLists.txt Foundation source registration
Review details
  • Files reviewed: 13/13 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Core/Foundation/Source/StandardStreamLogger_PosixOps.inl Outdated
bkaradzic and others added 2 commits September 10, 2026 16:33
Follow up on the review of #233. Make private stream copies
non-inheritable, create Android pipes atomically close-on-exec, and
preserve target inheritance flags during redirection and restoration.
Keep Windows CRT descriptor modes and unavailable GUI streams intact.

Apply platform-specific byte limits to complete and partial log lines,
including Apple's persisted dynamic-content budgets. Preserve UTF-8
boundaries and CRLF without changing the original-stream tee.

Add lifecycle, inheritance, chunking, and POSIX descriptor regression
coverage, and document the remaining process-creation synchronization
requirement on platforms without atomic primitives.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 88569c10-a7ff-4373-9a58-afa9c68b8c09
Use the checked pipe/fcntl fallback for desktop POSIX tests, avoiding
an implicit dependency on GNU pipe2 declarations. Preserve Android's
atomic O_CLOEXEC path and clarify the fallback's serialization requirement.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 54aaa1e1-b4b3-46e7-9de4-5a56add4ac42
@bkaradzic-microsoft
bkaradzic-microsoft force-pushed the fix/standard-stream-logger-followups branch from 93857c4 to 9b44d12 Compare September 10, 2026 23:37
@bkaradzic-microsoft
bkaradzic-microsoft enabled auto-merge (squash) September 11, 2026 00:12
bkaradzic-microsoft added a commit to BabylonJS/BabylonNative that referenced this pull request Sep 11, 2026
Updates the JsRuntimeHost pin from
`a6b98eaa1a9887b35adceed21f8c7d44c4f38e43` to
`f47991dd5729fac1d6d477e66ed8a843da1d4832`, the latest upstream `main`.

Includes BabylonJS/JsRuntimeHost#232:

- Dispatches V8 foreground tasks through AppRuntime so asynchronous
WebAssembly compilation promises settle instead of hanging.
- Shares the delayed-task scheduler between V8 foreground work and the
scheduling polyfill, with explicit ownership and shutdown handling.

This is a one-line dependency-pin update based on current Babylon Native
`master`.

The standard-stream logger follow-up,
BabylonJS/JsRuntimeHost#236, is still open and
is not included in this revision.

Co-authored-by: Branimir Karadzic <branimirkaradzic@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 88569c10-a7ff-4373-9a58-afa9c68b8c09

@bghgary bghgary left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Reviewed by Copilot on behalf of @bghgary]

Concerns inline.

Comment thread Core/Foundation/Source/StandardStreamLogger_Windows.cpp
Comment thread Core/Foundation/Source/StandardStreamLogger_Windows.cpp Outdated
Install the original CRT translation mode with each redirect and restore.
Keep private tee descriptors binary and non-inheritable in both the CRT
table and the kernel, and decode UTF-16 only for platform diagnostics.

Cover active and restored modes, original bytes, spawn startup metadata,
and streaming UTF-16 decoding. Document that reconstructed descriptors
do not preserve other CRT flags, including append mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 48fa7ec8-0cf6-48a0-b836-10b7ace38c1a
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.

5 participants