Skip to content

Unify scope boundaries and Ops semantics; document structured concurrency model - #57

Merged
lePereT merged 8 commits into
nextfrom
better_scope
Jan 8, 2026
Merged

Unify scope boundaries and Ops semantics; document structured concurrency model#57
lePereT merged 8 commits into
nextfrom
better_scope

Conversation

@lePereT

@lePereT lePereT commented Dec 22, 2025

Copy link
Copy Markdown
Contributor

What type of PR is this? (check all applicable)

  • 🍕 Feature
  • ✅ Test

Description

This PR strengthens the structured concurrency core and improves diagnostic consistency across Lua runtimes.

It includes two related changes:

  1. Scope semantics and boundaries
  • Updates fibers.scope to provide stable, predictable structured concurrency semantics for long-running, I/O-heavy systems.
  • Establishes structural lifetime on join: attached child scopes are joined by the parent (including child finalisers) in attachment order.
  • Introduces an explicit admission gate (close()), and ensures cancellation closes admission and cascades downward.
  • Treats cancellation as a first-class termination mode distinct from failure, using a dedicated cancellation sentinel.
  • Provides scope-aware op helpers with status-first boundaries (try/perform, join_op, run, run_op) and structured reports for child outcomes and finaliser errors.
  • Ensures join/finalisation is non-interruptible by running in a join worker and using op.perform_raw.
  1. Coroutine-safe xpcall traceback splicing (Lua 5.1 environments)
  • Revises the local coxpcall implementation to make traceback output better match LuaJIT by:

    • using debug.traceback(co, ...) for the failing coroutine, and
    • splicing outer call-site frames by walking the coroutine parent chain with a synthetic xpcall boundary per hop.
  • Preserves key semantics:

    • pcall continues to propagate the original error object unchanged;
    • xpcall(f, debug.traceback) continues to behave as expected;
    • handler faults are reported as handler faults.

Tests:

  • Adds/updates scope tests covering structural join behaviour, admission close/cancel behaviour, cancellation vs failure accounting, and boundary helpers (join_op/run/run_op).

Manual test

  • 👍 yes

Manual test description

  • Exercised scope creation/spawn/cancel/join sequences in a small local harness (listener → child scope → nested work) and verified:

    • cancellation does not mark the scope failed;
    • join drains attached children and runs finalisers deterministically;
    • tracebacks include failing coroutine frames plus outer call-site frames under Lua 5.1-style coroutine-unsafe xpcall.

Added tests?

  • 👍 yes

Added to documentation?

  • 🙅 no documentation needed

[optional] Are there any post-deployment tasks we need to perform?

None

@lePereT
lePereT requested review from corp0529 and cpunt December 22, 2025 15:34
Comment thread src/coxpcall.lua

local kept = {}
for line in tb:gmatch('[^\n]+') do
if line ~= 'stack traceback:'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

magic strings here looks brittle, could we have a single source of truth for the function names and these finds, possibly constructing the table of functions in a single place. Otherwise, if function names change, this will break tracing silently.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

very good point! will think on what we can do here

Comment thread src/coxpcall.lua
marker = marker or "\t[C]: in function 'xpcall'"

local out = tb_inner
local parent = coromap[co]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could a bug introduce an infinite parent loop here? Should we guard against that?

Comment thread src/fibers.lua
status = nil, -- 'ok'|'cancelled'|'failed'
primary = nil, -- primary/reason (for non-ok)
results = nil, -- packed results (for ok)
-- report = nil, -- optional: ScopeReport

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.

Do we not need this?

@cpunt cpunt 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.

Lgtm. Spent some time reading the comments, playing with the new semantics, and trying debug mode (super helpful). If @corp0529 is happy, I’m happy to get this in.

@lePereT
lePereT merged commit b9bc988 into next Jan 8, 2026
1 check passed
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.

3 participants