From 1ad4528975d48d6fe3186dab7ecd5e7c7af303f8 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 25 Apr 2019 18:14:41 -0700 Subject: [PATCH] lntest: use test subscription to prevent SubscribeChannelGraph race This race was possible due to us making a subscription request before the ChannelRouter has started. We address it by creating a dummy subscription before proceeding to the real one to ensure we can do so successfully. We use a dummy one in order to not consume an update from the real one. This addresses the common "timed out waiting for opened channel" flake within the integration test suite since the subscription was never properly created, so we'd never be notified of when new graph updates were received. --- lntest/node.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/lntest/node.go b/lntest/node.go index 26cb6cab..91bb6238 100644 --- a/lntest/node.go +++ b/lntest/node.go @@ -494,6 +494,43 @@ func (hn *HarnessNode) initLightningClient(conn *grpc.ClientConn) error { return err } + // Due to a race condition between the ChannelRouter starting and us + // making the subscription request, it's possible for our graph + // subscription to fail. To ensure we don't start listening for updates + // until then, we'll create a dummy subscription to ensure we can do so + // successfully before proceeding. We use a dummy subscription in order + // to not consume an update from the real one. + err = WaitNoError(func() error { + req := &lnrpc.GraphTopologySubscription{} + ctx, cancelFunc := context.WithCancel(context.Background()) + topologyClient, err := hn.SubscribeChannelGraph(ctx, req) + if err != nil { + return err + } + + // We'll wait to receive an error back within a one second + // timeout. This is needed since creating the client's stream is + // independent of the graph subscription being created. The + // stream is closed from the server's side upon an error. + errChan := make(chan error, 1) + go func() { + if _, err := topologyClient.Recv(); err != nil { + errChan <- err + } + }() + + select { + case err = <-errChan: + case <-time.After(time.Second): + } + + cancelFunc() + return err + }, DefaultTimeout) + if err != nil { + return err + } + // Launch the watcher that will hook into graph related topology change // from the PoV of this node. hn.wg.Add(1)