Commit Graph

13 Commits (23e26b5b320caa5907ccda4fd373e52abbb80d5f)

Author SHA1 Message Date
Gud Boi 23e26b5b32 Bound `Portal.cancel_actor()` frame sends
A cancel RPC could stall forever in complete-frame transport
shielding before the peer received it, bypassing the outer ack
timeout and blocking graceful supervision.

- thread one absolute deadline from `Portal.cancel_actor()` through
  the private `Start` publication path
- force-close a partial-frame stream before releasing its send lock
- keep ordinary sends unbounded and preserve pending cancellation
- document the current `Start -> StartAck -> CancelAck` exchange and
  link the dedicated `Cancel` msg follow-up in #506
- cover partial publication and the shared send/ack timeout budget

Prompt-IO: ai/prompt-io/opencode/20260821T023537Z_ae6f2ac3_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-21 15:03:35 -04:00
Gud Boi 086962ca36 Preserve cancellation over shielded `send_all()` errors
The frame-publication shield added in `88a23449` checks for
pending cancellation only after a successful write. If actor
teardown closes the stream first, `ClosedResourceError` escaped
as `TransportClosed` and could defeat the caller's cancel scope.

Check for pending cancellation on the transport-error path before
normalizing the close. Genuine stream errors retain their existing
translation when no cancellation is active.

The cancellation-first path can swap which nested debugger
intermediary renders as the immediate source vs. relay. Keep
assertions over both actor levels while accepting either valid role.

Prompt-IO: ai/prompt-io/opencode/20260820T143845Z_559fd0f1_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-21 15:03:34 -04:00
Gud Boi 643e1c861b Complete IPC frames before sender cancellation
Cancellation inside `send_all()` can publish a partial frame. Closing
the actor-wide stream preserved framing but destroyed every context
on the channel and replaced primary errors with `TransportClosed`.

Deats,
- shield complete frame publication, then deliver pending
  cancellation
- keep the shared channel reusable after context-local cancellation
- absorb transport closure while reporting an unshippable overrun
- cover mid-frame cancellation and failed overrun error shipment

This deliberately defers cancellation until the current frame write
resolves; channel teardown remains the fallback for broken peers.

Prompt-IO: ai/prompt-io/opencode/20260819T234824Z_557065d8_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-21 15:03:34 -04:00
Gud Boi ecf89bfaac Close interrupted `MsgTransport.send()` streams
`SendStream.send_all()` can raise `trio.Cancelled` after writing an
arbitrary prefix of the four-byte length header and payload. The
peer can no longer distinguish a following msg boundary.

Close the stream under a shield before propagating cancellation so
callers can not append another msg to an indeterminate byte stream.

Caught-during: review remediation
Found-via: prospective P2 cancellation review

Review: PR #481 (opencode)
https://github.com/goodboy/tractor/pull/481#pullrequestreview-4956692120

Prompt-IO: ai/prompt-io/opencode/20260818T193001Z_bf06b4f8_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-21 15:03:34 -04:00
Gud Boi f454cefe56 Enforce `get_rt_dir()` ownership on POSIX
Linux previously accepted a pre-existing runtime bindspace without
checking its owner or mode, even though Darwin enforced both. Share
the POSIX directory guard so every managed root and subdir rejects
non-directories and foreign UIDs before changing permissions.

Normalize owner-controlled bindspaces to `0o700` and add Linux
regressions for mode repair, foreign ownership, and non-directory
paths.

Review: PR #480 (goodboy)
https://github.com/goodboy/tractor/pull/480

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-14 18:40:23 -04:00
Gud Boi ac61d7a5bf Use a short UDS reaper test bindspace
Darwin's pytest `tmp_path` can already exceed the 104-byte AF_UNIX
budget before appending either synthetic socket filename. That made
the new sentinel-policy regression fail identically in both macOS
matrix legs without exercising reaper behavior.

Allocate the test's real socket files under a short
`/tmp/tractor-reap-*` directory and retain scoped cleanup.

Review: PR #480 (goodboy)
https://github.com/goodboy/tractor/pull/480

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-14 10:59:07 -04:00
Gud Boi 16dd876b0c Make UDS reaping platform-aware
Moving Darwin sockets to `/tmp/tractor-<uid>` left pytest and the
standalone reaper searching only `XDG_RUNTIME_DIR`. Enabling that
shared bindspace naively would also let automatic session cleanup
unlink an independent live `registry@1616.sock`.

Resolve the runtime's actual default UDS bindspace on every platform.
Exclude the pid-less registry sentinel from automatic cleanup while
retaining explicit CLI removal, and document that destructive choice.

Cover bindspace resolution and automatic-vs-explicit sentinel policy.

Review: PR #480 (goodboy)
https://github.com/goodboy/tractor/pull/480

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-14 10:36:27 -04:00
Gud Boi 0d6d7c2a63 Keep UDS post-kill cleanup best-effort
`unlink_uds_bind_addrs()` reconstructs self-assigned socket paths
after a hard kill. An over-budget bindspace can make
`UDSAddress.get_sockname()` raise before the guarded `os.unlink()`,
replacing the original supervision outcome after the child is gone.

Catch and report reconstruction failures, then skip cleanup without
raising. Cover the overflow path and prove no unlink is attempted.

Review: PR #480 (goodboy)
https://github.com/goodboy/tractor/pull/480

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-13 18:57:13 -04:00
Gud Boi 340d506940 Bound generated UDS socket paths
Actor names and custom runtime subdirs can otherwise produce unsafe
or overlong pathname sockets after moving Darwin's bindspace to
`/tmp`.

Deats,
- hash unsafe or over-budget actor names while retaining `@pid.sock`
- share deterministic naming with post-kill socket cleanup
- enforce Linux and Darwin `sun_path` byte budgets
- restore non-Darwin dir validation and mode `0700`
- validate every nested Darwin runtime-dir component

Review: PR #480 (goodboy)
https://github.com/goodboy/tractor/pull/480

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-13 18:40:55 -04:00
Gud Boi 634d914161 Use short Darwin UDS runtime paths
`platformdirs` can place the runtime dir deep below a pytest temp
home, pushing `registry@1616.sock` past Darwin's 104-byte
`AF_UNIX` limit.

Use a compact `/tmp/<app>-<uid>` root on Darwin and secure it
before allocating socket paths:
- require a real, current-user-owned dir via `lstat()`
- tighten existing roots to mode `0700`
- reject symlinks and unsafe nested dirs

Cover the path budget, mode, and symlink rejection.

Caught-during: review remediation
Found-via: `/run-tests` test_macos_rt_dir_fits_uds_path_limit

Review: PR #480 (goodboy,copilot-pull-request-reviewer[bot])
https://github.com/goodboy/tractor/pull/480

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-13 16:39:32 -04:00
Gud Boi f3441a6790 Update tests+examples imports for new subpkgs
Adjust all `tractor._state`, `tractor._addr`,
`tractor._supervise`, etc. refs in tests and examples
to use the new `runtime/`, `discovery/`, `spawn/` paths.

Also,
- use `tractor.debug_mode()` pub API instead of
  `tractor._state.debug_mode()` in a few test mods
- add explicit `timeout=20` to `test_respawn_consumer_task`
  `@tractor_test` deco call

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-04-02 17:59:13 -04:00
Tyler Goodlet 79f502034f Don't hard code runtime-dir, read it with `._state.get_rt_dir()` 2025-08-18 21:30:48 -04:00
Tyler Goodlet 00112edd58 UDS: implicitly create `Address.bindspace: Path`
Since it's merely a local-file-sys subdirectory and there should be no
reason file creation conflicts with other bind spaces.

Also add 2 test suites to match,
- `tests/ipc/test_each_tpt::test_uds_bindspace_created_implicitly` to
  verify the dir creation when DNE.
- `..test_uds_double_listen_raises_connerr` to ensure a double bind
  raises a `ConnectionError` from the src `OSError`.
2025-08-18 21:30:48 -04:00