Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Pin the mutable-image restore fields and re-derive its contract when a caller lands (#1963 follow-up)

Open
#2,019 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Documentation
Clarity
Mostly clear
Activity status
Active
Tech stack
c
Domain
backend, testing

Research direction

Start with the contract block above the four entry points in internal.h and test_mutable_image_transaction in the test file; inspect relation.c and run probes rather than relying on the existing claims. Re-derive each return route and mutation-check each assertion when a production caller lands, then update the contract and coverage claims to match observed behavior.

Written by the indexing model from the issue text.

Description

Follow-up to #2018, which lands the governed mutable relation-image
transaction with tests as its only caller. These items are all unreachable
from production code today — grep -rn "col_rel_mutable_image_" wirelog/
outside relation.c and internal.h is empty — and each becomes live the
moment the first production caller does.

Restore fields that commit performs and nothing pins

col_rel_mutable_image_commit restores these from the captured old after
*source = *image. Deleting any one leaves the suite green:

  • storage_owner_identity — fed by the same local as relation_identity, so
    only a selective drop escapes. Observable via arrangement.c:1088's
    storage_owner_identity != relation_identity invariant once an alias borrow
    reaches a committed image.
  • memory_budget_denial_pending — a dropped restore forgets a denial recorded
    before the transaction, so the next ENOMEM would not remap to ENOSPC.
  • deferred_relation_next / deferred_relation_session — NULL in every
    fixture; needs a session fixture to observe.

Guards with no negative coverage

  • col_rel_mutable_image_validate's col_rel_storage_alias_borrow_count check
    is shadowed in prepare by col_rel_published_writer_acquire's own alias
    check, so dropping it leaves the suite green. It still matters inside
    commit, where the writer is already held.
  • commit's EBUSY pre-flight is driven by exactly one case, and that case
    reaches the refusal through validate(image)'s descriptor arithmetic rather
    than through the image->name clause it is named for.
  • The duplicate descriptor/pool-name assertion is over-determined: after
    descriptor_reserved_bytes += name_bytes, col_rel_image_token_valid also
    fails on token->bytes, so it cannot isolate the selector.

Fixtures pinning states no production path produces

Both are documented as synthetic in the tests, and both must be re-derived from
a real instance if one ever appears:

  • The pool-name fixture builds a heap descriptor charged for the struct alone
    while a separate pool-name token is live. session_pool_rel_promote does not
    produce that: it allocates the descriptor with the name already charged and
    only then moves the token, so its window is double-charged and refused. The
    fixture exists because it is the only route to commit's pool-name transfer
    branch.
  • The post-commit control offsets storage_generation by 7 so the assertion can
    distinguish a restored generation from an inherited one. The offset must stay
    larger than the image's own storage-generation growth or the assertion goes
    quiet without failing.

Documentation, and how to re-derive it

The internal.h contract block above the four entry points was rewritten four
times during review and was wrong the first three. Every correction came from
running a probe; none came from reading the source. When the first production
caller lands, re-derive that block and every coverage claim in
test_mutable_image_transaction from running probes — each return route
exercised and observed, each assertion mutation-checked — rather than by
editing the existing text.

Two known imprecisions elsewhere, both currently harmless:

  • col_rel_mutable_image_prepare releases the writer with (void) on its error
    path, where commit and discard both abort(). It matches
    col_rel_published_writer_acquire's own convention, so this is a consistency
    question rather than a defect.
  • discard has a fourth abort() on a failed writer release, reachable only if
    another thread stomps the gate words. The contract does not enumerate it
    because it is not a caller-visible condition.

Unrelated, noticed while working here

wirelog/columnar/expr.c:643 accepts a scalar-addon descriptor that declares
WIRELOG_EXTENSION_VALUE_BOOL as its result_type in a value position and then
uses whatever the callback writes into result. A descriptor can misdeclare its
result type and nothing reports it.

relation.c has a comment, "Physical old image retires first", whose ordering is
not pinned: moving the three col_rel_release_reservation_or_abort calls before
col_rel_free_contents(&old) leaves the suite green. This test file already owns
a witness for that class of invariant in observe_overwrite_retirement.

Dominant language
C
Stars
18
Forks
2
Avg merge
6h 16m
Merged PRs (30d)
286

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from semantic-reasoning/wirelog

All issues in semantic-reasoning/wirelog

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.