@@ -88,7 +88,7 @@ func (c *walletLifecycleCoordinator) runStop() {
8888 return
8989 }
9090
91- c .entry . teardownErr = c . entry . wallet . finishRuntime ()
91+ c .finishRuntime ()
9292}
9393
9494// abortStart cancels and joins setup before publishing the winning Start
@@ -113,7 +113,7 @@ func (c *walletLifecycleCoordinator) abortStart(req startWalletRequest,
113113
114114 req .result <- startErr
115115
116- c .entry . teardownErr = c . entry . wallet . finishRuntime ()
116+ c .finishRuntime ()
117117}
118118
119119// failStart publishes a setup or worker-publication failure and completes
@@ -128,7 +128,7 @@ func (c *walletLifecycleCoordinator) failStart(req startWalletRequest,
128128
129129 req .result <- startErr
130130
131- c .entry . teardownErr = c . entry . wallet . finishRuntime ()
131+ c .finishRuntime ()
132132}
133133
134134// stopRuntime stops a successfully published runtime.
@@ -140,7 +140,33 @@ func (c *walletLifecycleCoordinator) stopRuntime() {
140140 return
141141 }
142142
143- c .entry .teardownErr = c .entry .wallet .finishRuntime ()
143+ c .finishRuntime ()
144+ }
145+
146+ // finishRuntime joins blocking worker teardown outside the coordinator and
147+ // records completion for the exact runtime before the coordinator exits.
148+ func (c * walletLifecycleCoordinator ) finishRuntime () {
149+ w := c .entry .wallet
150+ teardownDone := make (chan walletTeardownResult , 1 )
151+
152+ go func () {
153+ teardownDone <- walletTeardownResult {
154+ wallet : w ,
155+ err : w .finishRuntime (),
156+ }
157+ }()
158+
159+ result := <- teardownDone
160+ if result .wallet != w {
161+ c .entry .teardownErr = fmt .Errorf (
162+ "%w: teardown result runtime changed" ,
163+ ErrWalletNotManaged ,
164+ )
165+
166+ return
167+ }
168+
169+ c .entry .teardownErr = result .err
144170}
145171
146172// validateSetupResult rejects a setup completion for any other runtime.
0 commit comments