Skip to content

Commit 8435549

Browse files
committed
openchannel: cancel shims with a live context
In manager.go, deferred shim cleanup was calling FundingStateStep with the original request ctx. If the user had already canceled that context, the cleanup RPC would run with a canceled context and could fail to remove the pending shim. I changed that cleanup path to use context.WithoutCancel(ctx) so the cancellation RPC still has a live context.
1 parent b1afc98 commit 8435549

2 files changed

Lines changed: 44 additions & 5 deletions

File tree

staticaddr/openchannel/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func (m *Manager) openChannelPsbt(ctx context.Context,
497497
},
498498
}
499499
_, err := m.cfg.LightningClient.FundingStateStep(
500-
ctx, cancelMsg,
500+
context.WithoutCancel(ctx), cancelMsg,
501501
)
502502
if err != nil {
503503
log.Errorf("Error canceling shim: %v\n", err)

staticaddr/openchannel/manager_test.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -608,9 +608,10 @@ type mockLndClient struct {
608608

609609
rawClient lnrpc.LightningClient
610610

611-
mu sync.Mutex
612-
fundingStepIdx int
613-
fundingStepErr error
611+
mu sync.Mutex
612+
fundingStepIdx int
613+
fundingStepErr error
614+
fundingStepCtxErrs []error
614615
}
615616

616617
func (m *mockLndClient) RawClientWithMacAuth(
@@ -620,13 +621,14 @@ func (m *mockLndClient) RawClientWithMacAuth(
620621
return ctx, 0, m.rawClient
621622
}
622623

623-
func (m *mockLndClient) FundingStateStep(_ context.Context,
624+
func (m *mockLndClient) FundingStateStep(ctx context.Context,
624625
_ *lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) {
625626

626627
m.mu.Lock()
627628
defer m.mu.Unlock()
628629

629630
m.fundingStepIdx++
631+
m.fundingStepCtxErrs = append(m.fundingStepCtxErrs, ctx.Err())
630632

631633
return &lnrpc.FundingStateStepResp{}, m.fundingStepErr
632634
}
@@ -746,6 +748,43 @@ func TestStreamOpenError(t *testing.T) {
746748
// Verify that the shim was canceled via FundingStateStep.
747749
lnClient.mu.Lock()
748750
require.Equal(t, 1, lnClient.fundingStepIdx)
751+
require.Len(t, lnClient.fundingStepCtxErrs, 1)
752+
require.NoError(t, lnClient.fundingStepCtxErrs[0])
753+
lnClient.mu.Unlock()
754+
}
755+
756+
// TestStreamOpenErrorWithCanceledContext verifies that deferred shim cleanup
757+
// still uses a live context even if the caller canceled the original request.
758+
func TestStreamOpenErrorWithCanceledContext(t *testing.T) {
759+
t.Parallel()
760+
761+
mockRaw := &mockRawLnrpcClient{
762+
openErr: errors.New("connection refused"),
763+
}
764+
lnClient := &mockLndClient{rawClient: mockRaw}
765+
766+
manager := &Manager{
767+
cfg: &Config{
768+
LightningClient: lnClient,
769+
ChainParams: &chaincfg.RegressionNetParams,
770+
},
771+
}
772+
773+
ctx, cancel := context.WithCancel(context.Background())
774+
cancel()
775+
776+
req := &lnrpc.OpenChannelRequest{
777+
LocalFundingAmount: 100000,
778+
MinConfs: defaultUtxoMinConf,
779+
}
780+
781+
_, err := manager.openChannelPsbt(ctx, req, nil, 0)
782+
require.ErrorContains(t, err, "opening stream to server failed")
783+
784+
lnClient.mu.Lock()
785+
require.Equal(t, 1, lnClient.fundingStepIdx)
786+
require.Len(t, lnClient.fundingStepCtxErrs, 1)
787+
require.NoError(t, lnClient.fundingStepCtxErrs[0])
749788
lnClient.mu.Unlock()
750789
}
751790

0 commit comments

Comments
 (0)