Skip to content

Effect handler-owned mut state diverges at top level vs inside main (HTTP/C-callback boundary) #156

Description

@MelbourneDeveloper

Summary

Effect-handler-owned state held in a top-level mut cell diverges from the
identical program written inside fn main(). When the handler that owns the
mut state is installed across the C HTTP-callback boundary (a request handler's
perform resolving to the active handler), de-maining the program — moving the
mut cells and handle … in to module top level, where main is synthesised
from trailing statements — produces wrong output and lost state.

Repro

examples/tested/effects/http_state_levels.ospml (and its .osp twin) only
pass with an explicit main () = wrapper around the mut diskBytes/requests/ tasks/taskCount cells + the handle Persist/Metrics/Db/Log … in runDemo ().
Lifting the same mut + handle to top level (the de-mained form used by the
other 7 effects pairs) changes the observed output:

  • expected (inside main): server replied 201, shutdown counts reflect all writes
  • actual (de-mained, top level): server replied 200, state reset / counts wrong

The other effects examples (handler_scoping, resume_*, fiber_effects)
de-main cleanly with byte-identical output and IR, so the divergence is
specific to handler-owned mut state that crosses the C HTTP-callback
boundary
at module top level.

Expected

A top-level script and the same code wrapped in fn main() must produce
byte-identical output and IR (the no-main invariant in
docs/specs/0023-LanguageFlavors.md [FLAVOR-ASSIGN] — main is synthesised from
trailing top-level statements, in both flavors). Handler-owned mut state must
survive across the HTTP/C-callback boundary regardless of whether the handler is
installed inside main or at top level.

Impact

  • Blocks de-maining http_state_levels (the canonical handler-owned-state-across-
    HTTP example, cited in docs/specs/0017-AlgebraicEffects.md).
  • Affects both flavors (.osp and .ospml).

Notes

Surfaced while removing needless main wrappers from the spec/example set. The
spec examples in 0017 that use top-level mut + handler for pure effects
de-main fine; only the HTTP/C-callback-boundary case diverges, which points at
the callback-boundary handler-resolution path rather than top-level mut per se.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingshowstopperCritical: blocks usage, must fix before release

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions