Skip to content

Replace tiny-process-library with SDK process code (CreateProcessW)#32

Merged
0xeb merged 6 commits intomainfrom
feature/replace-tiny-process-lib
Feb 17, 2026
Merged

Replace tiny-process-library with SDK process code (CreateProcessW)#32
0xeb merged 6 commits intomainfrom
feature/replace-tiny-process-lib

Conversation

@0xeb
Copy link
Copy Markdown
Owner

@0xeb 0xeb commented Feb 17, 2026

Summary

  • Replace FetchContent dependency on tiny-process-library with internal cross-platform process code adapted from copilot-sdk-cpp
  • Upgrade Win32 from CreateProcessA to CreateProcessW (Unicode) with STARTUPINFOEXW, explicit handle inheritance, and Job Object child cleanup
  • Rewrite StdioTransport from callback-based (deque + condition_variable) to synchronous pipe model with background stderr reader
  • Add 3 new test suites: stdio_lifecycle, stdio_stderr, stdio_timeout

Motivation

Downstream projects pulling libagents -> fastmcpp_core transitively inherit the tiny-process-library dep even though all the needed process functionality already exists in the SDK code. This PR eliminates that extra dependency and unifies on one process abstraction.

Changes

New files (src/internal/):

  • process.hpp — Cross-platform process API (fastmcpp::process:: namespace)
  • process_win32.cpp — Win32: CreateProcessW, STARTUPINFOEXW, explicit handle list, Job Object, CREATE_NO_WINDOW
  • process_posix.cpp — POSIX: fork/exec with error pipe for exec failure detection
  • process.cpp — Platform dispatcher

Modified files:

  • CMakeLists.txt — Remove TinyProcessLib FetchContent block, add src/internal/process.cpp
  • src/client/transports.cpp — Rewrite StdioTransport internals (public API unchanged via pimpl)
  • include/fastmcpp/client/transports.hpp — Add missing override on session_id()/has_session() (CI fix)
  • include/fastmcpp/providers/openapi_provider.hpp — Fix brace-init default param for AppleClang (CI fix)
  • tests/transports/stdio_failure.cpp — Remove #ifdef TINY_PROCESS_LIB_AVAILABLE guard

Test plan

  • 89/89 existing + new C++ unit tests pass (ctest --test-dir build -C Release)
  • stdio_client — keep-alive mode, one-shot mode, counter state persistence
  • stdio_failure — non-existent command throws TransportError
  • stdio_lifecycle — server crash, destructor cleanup, rapid sequential requests
  • stdio_stderr — log_file, log_stream, stderr in error messages
  • stdio_timeout — unresponsive server triggers 30s timeout
  • Zero references to TINY_PROCESS_LIB / tiny_process remain in tree
  • CI: Linux/macOS/Windows matrix

0xeb added 3 commits February 15, 2026 07:39
Generated Python CLI scripts now look for the fastmcpp binary next to
the script itself before falling back to PATH lookup. Fixes
FileNotFoundError on Windows where the binary isn't in PATH.
@0xeb 0xeb force-pushed the feature/replace-tiny-process-lib branch from 218be36 to 211c615 Compare February 17, 2026 02:42
…ssW)

Replace the FetchContent dependency on tiny-process-library with internal
cross-platform process code adapted from copilot-sdk-cpp. This eliminates
an external dependency that was transitively inherited by downstream
projects (libagents -> fastmcpp_core).

Win32 implementation upgraded from CreateProcessA to CreateProcessW:
- UTF-8/UTF-16 conversion via utf8_to_wide() helper
- STARTUPINFOEXW with explicit handle inheritance (PROC_THREAD_ATTRIBUTE_HANDLE_LIST)
- Job Object for automatic child cleanup
- CREATE_NO_WINDOW to prevent console popups
- Stderr redirected to NUL when not captured

StdioTransport rewritten from callback-based (deque + condition_variable)
to synchronous pipe model (direct read_line on stdout pipe), with a
background stderr reader thread in keep-alive mode to prevent pipe buffer
deadlock. Process liveness is checked during timeout polling (200ms
intervals) for fast failure detection when servers crash.

Also fixes two CI issues from PR #31:
- openapi_provider.hpp: brace-init default param -> explicit Options{}
- transports.hpp: add missing override on session_id/has_session

New tests: stdio_lifecycle, stdio_stderr, stdio_timeout.
All 89 tests pass.
@0xeb 0xeb force-pushed the feature/replace-tiny-process-lib branch from 211c615 to 8bf2fff Compare February 17, 2026 02:56
@0xeb 0xeb mentioned this pull request Feb 17, 2026
3 tasks
0xeb added 2 commits February 16, 2026 19:31
The template provider uses weakly_canonical() to resolve resource paths,
but skill_path_ was stored as absolute().lexically_normal(). On macOS,
/tmp is a symlink to /private/tmp, so weakly_canonical resolves it but
lexically_normal does not -- causing the is_within prefix check to fail
with "Skill path escapes root". Same issue on Windows with 8.3 short
names. Using weakly_canonical for skill_path_ ensures both sides of the
comparison use the same canonical form.
Test that SkillProvider and SkillsDirectoryProvider correctly handle
template resource reads when the skill path goes through a symlink
(POSIX) or NTFS junction (Windows). This catches the bug where
skill_path_ stored as lexically_normal() diverged from
weakly_canonical() in the template provider's is_within() check.

Tests:
- [link] Template reads through symlink/junction path
- [link-dir] Directory provider through symlink/junction
- [canonical-temp] Temp path with canonical differences
- [escape] Path traversal rejection (../secret.txt)
- [resources-mode] Resources mode through non-canonical path

Key implementation note: uses require() instead of assert() to avoid
side-effect-in-assert bugs in Release builds (NDEBUG strips assert).
@0xeb 0xeb force-pushed the feature/replace-tiny-process-lib branch from 5b90817 to 333c067 Compare February 17, 2026 03:59
@0xeb 0xeb merged commit 97d9bc1 into main Feb 17, 2026
6 of 7 checks passed
@0xeb 0xeb deleted the feature/replace-tiny-process-lib branch February 17, 2026 16:25
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