rocq/theories/Shutdown.v
Serialized shutdown of the selected user-glibc: callbacks, stdout obligations and a soft or hard host-exit handoff. This is a logical lifecycle, not native callback execution or host termination. In particular, a handoff does not itself emit ProcessExit.
Callback calling conventions retain their argument, not just its address.
| | | AtExit | function : name | |
| | | OnExit | ||
| | | CxaExit |
A registration instance: registering one function twice gives two tokens.
| registration_token | : nat | |
| registration_callback |
Soft handoff calls host exit; hard handoff calls host _Exit.
| | | SoftExit | ||
| | | HardExit |
The selected TLS destructor loop is empty. Done is derived from phase: registration has closed in Cleanup and cannot reopen.
| | | Tls | ||
| | | Handlers | ||
| | | InCallback | active : registration | |
| | | Cleanup | ||
| | | HandedOff | kind : handoff_kind |
Pending registrations are newest first; consumed tokens retain history even when a recursive exit abandons the active callback.
| shutdown_at | ||
| shutdown_status | : Z | |
| shutdown_pending | : listregistration | |
| shutdown_consumed | : listnat | |
| shutdown_stdout |
Protocol actions are not arbitrary callback traces or native events.
| | | EmptyTls | ||
| | | InvokeCallback | entry : registration status : Z | |
| | | ReturnCallback | ||
| | | RegisterCallback | entry : registration | |
| | | RecursiveExit | status : Z | |
| | | ShutdownOutput | action : stream_action | |
| | | StartCleanup | ||
| | | Handoff | kind : handoff_kind status : Z |
The protocol permits finite unfinished callbacks/cleanup. Successful registration is conditional, and fresh tokens cannot reuse an instance. Cleanup only projects settlement/error, not all of native _IO_cleanup. Hard exit does not flush or discard outstanding output.
A source and selected action fix the logical endpoint. This lets a caller name its next cutpoint without supplying endpoint validity again.
Explore proof 3 tactics
Initial goal
intros sh action left right Hl Hr
inversion Hl ; subst ; inversion Hr ; subst ; try reflexivity
2 openfocused goal
all: match goal withH1 : stream_step , H2 : stream_step |- _⇒assert q1 = q2 by eapply stream_step_target ; eauto ; subst ; reflexivityend
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A finite shutdown prefix; no rule promises eventual completion.
All pending and consumed registration-instance tokens are distinct.
Moving a fresh registration token into the pending stack preserves uniqueness.
Explore proof 3 tactics
Initial goal
intros before after token Hnd Hfresh
apply Permutation_NoDupPermutation_middlebefore after token
constructor ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Pop-before-call and fresh successful registration preserve instance uniqueness.
Explore proof 5 tactics
Initial goal
intros s action s′ H Hunique
destruct H ; unfold shutdown_unique in * ; simpl in * ; auto
2 openfocused goal
–rewrite <- app_assoc
2 opendeferred goal
exact Hunique
deferred goal
–apply shutdown_unique_insert ; assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
No registration instance is invoked twice, even across recursive exit.
Explore proof 5 tactics
Initial goal
intros s actions s′ H
induction H ; auto |
intros Hu
apply IHshutdown_run
eapply shutdown_step_unique ; eauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Tokens invoked by one action; registering and returning invoke none.
Consumed history grows by exactly the invoked instances, in invocation order.
Explore proof 2 tactics
Initial goal
intros s action s′ H
destruct H ; simpl ; try reflexivity ; symmetry ; apply app_nil_r
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The history accounts for every callback invocation in a finite run.
Explore proof 4 tactics
Initial goal
intros s actions s′ H
induction H ; simpl ; symmetry ; apply app_nil_r |
rewrite IHshutdown_run , shutdown_step_consumed_ _ _ H , app_assoc
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Every invoked token occurs once in the trace, not merely in final pending state.
Explore proof 7 tactics
Initial goal
intros s actions s′ H Hu
pose proof shutdown_run_unique_ _ _ H Hu as Hfinal
unfold shutdown_unique in Hfinal
apply NoDup_app_remove_r in Hfinal
rewrite shutdown_consumption_ _ _ H in Hfinal
apply NoDup_app_remove_l in Hfinal
exact Hfinal
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Recursive exit and _exit install their own signed status, not the old exit's.
Explore proof 2 tactics
Initial goal
intros s action s′ H
destruct H ; simpl ; auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Cleanup and either handoff have closed registration.
Closing registration is permanent through every remaining finite prefix.
Explore proof 5 tactics
Initial goal
intros s actions s′ H
induction H ; auto |
intros Hclosed
apply IHshutdown_run
destruct H ; simpl in * ; tauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A user-glibc handoff has no further lifecycle step.
Explore proof 4 tactics
Initial goal
intros s kind action s′ Hat H
destruct H ; simpl in Hat ; try discriminate
apply Hkind
exact Hat
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Once cleanup starts, registration cannot succeed.
Explore proof 3 tactics
Initial goal
intros s entry s′ Hat H
inversion H ; subst
discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Project only the stdout actions; handoff is not an output error/discard.
The stdout projection is exactly a stream run, including unfinished obligations.
Explore proof 5 tactics
Initial goal
intros s actions s′ H
induction H ; constructor |
destruct H ; simpl in * ; try exact IHshutdown_run
2 openfocused goal
–eapply stream_next ; eassumption | exact IHshutdown_run
deferred goal
–eapply stream_next ; eassumption | exact IHshutdown_run
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Shutdown neither loses accepted bytes nor mistakes error discard for delivery.
Explore proof 4 tactics
Initial goal
intros
apply stream_accounting
apply shutdown_stream_run
assumption
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Host completion is a separate, uninstantiated contract. Requiring its witness does not claim native host handlers or loader finalization safe.
Completion contributes exactly one exit observation, never a callback trace.
Explore proof 3 tactics
Initial goal
intros host s events H
destruct H
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Read main's W-class return as a signed C int, before callbacks see it.
Signed interpretation does not change the final process low byte.
Explore proof 11 tactics
Initial goal
intros bits
unfold main_status , sign_extension , process_status
assert Hmod : bits mod 2 ^ 32 mod 256 = bits mod 256
2 openfocused goal
{apply Z.mod_mod_divide
2 opendeferred goal
exists 2 ^ 24
2 opendeferred goal
reflexivity
deferred goal
destruct 2 ^ 31 ≤? bits mod 2 ^ 32 ; | exact Hmod
rewrite Zminus_mod , Hmod
replace 2 ^ 32 mod 256 with 0 by reflexivity
rewrite Z.sub_0_r , Z.mod_mod by lia
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
No locals means the core return invalidates exactly nothing.
Explore proof 3 tactics
Initial goal
intros c H
rewrite H
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Evidence for the narrow main-return bridge: no callers or locals, non-doomed W return, and an actual evaluated integer at the return site.
This return really produces the core terminal, and its retained snapshot is final memory. No successor is added to ExternalMachine.Stopped.
Explore proof 9 tactics
Initial goal
intros ge c bits label & value & Hat & Hd & Hl & Hc & Hr & Hv
split ; | apply return_no_locals_memory ; assumption
unfold Semantics.step
rewrite Hat
unfold jump_step
rewrite Hd , Hr , Hv
unfold return_step
rewrite Hl , Hc
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A doomed return cannot use this bridge, regardless of its evaluated word.
Explore proof 3 tactics
Initial goal
intros ge c bits why _ & _ & _ & Hd & _
rewrite Hd
discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A live-local return needs a different final-memory argument.
Explore proof 2 tactics
Source script
Main initializes the lifecycle only with actual return-site evidence.
The two's-complement -1 reaches callbacks as -1, and the host reports 255.
Explore proof 2 tactics
Initial goal
vm_compute
auto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Public lifecycle boundaries
Two registrations of the same function remain distinct instances.
The second registration deliberately repeats the function, not its token.
A handler dynamically registered by the newest callback.
A dynamically added callback runs before the older pending registration.
Explore proof 12 tactics
Initial goal
intros q
eapply shutdown_next ; apply shutdown_tls |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_register ; simpl ; intuition congruence |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_cleanup |
eapply shutdown_next ; apply shutdown_soft |
constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Recursive exit abandons the active callback and supplies -1 to older ones.
Explore proof 10 tactics
Initial goal
intros q
eapply shutdown_next ; apply shutdown_tls |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_recursive |
eapply shutdown_next ; apply shutdown_tls |
eapply shutdown_next ; apply shutdown_invoke |
eapply shutdown_next ; apply shutdown_return |
eapply shutdown_next ; apply shutdown_cleanup |
eapply shutdown_next ; apply shutdown_soft |
constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
An active registration instance cannot be registered again with its old token.
Explore proof 4 tactics
Initial goal
intros q s′ H
inversion H ; subst
simpl in *
tauto
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A callback's _exit(98) replaces exit(31), leaving handlers and output untouched.
Explore proof 3 tactics
Initial goal
apply shutdown_hard
intros kind H
discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Hard exit can replace status after cleanup has closed registration too.
Explore proof 4 tactics
Initial goal
intros q
apply shutdown_hard
intros kind H
discriminate
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Its conditional host observation reports the hard exit's own status.
Explore proof 3 tactics
Initial goal
intros host q H
apply observe_host_exit
exact H
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Partial delivery followed by output error can leave a byte outstanding at handoff.
Explore proof 10 tactics
Initial goal
eapply shutdown_next
3 openfocused goal
shelved goal
–apply shutdown_cleanup_output ; intros bytes H ; discriminate |
3 opendeferred goal
shelved goal
apply stream_deliver65 66; 90 false
2 opendeferred goal
discriminate
deferred goal
–eapply shutdown_next
3 openfocused goal
shelved goal
+apply shutdown_cleanup_output ; intros bytes H ; discriminate |
3 opendeferred goal
shelved goal
apply stream_discard66 90 false
2 opendeferred goal
discriminate
deferred goal
+eapply shutdown_next ; apply shutdown_soft |
constructor
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A concrete no-locals main return: there is no invented stopped-state evidence.
The return-site predicate checks the concrete return value and core transition.
Explore proof 3 tactics
Initial goal
intros ge m
exists TInt1, Const4294967295
repeat split ; reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.