@@ -101,7 +101,7 @@ func getClientPlatform() string {
101101// Allows for overriding in tests.
102102var startTunnel func (ctx context.Context , config * DialerConfig ) (psiphonTunnel , error ) = psiphonStartTunnel
103103
104- func psiphonStartTunnel (ctx context.Context , config * DialerConfig ) (psiphonTunnel , error ) {
104+ func psiphonStartTunnel (tunnelCtx context.Context , config * DialerConfig ) (psiphonTunnel , error ) {
105105 if config == nil {
106106 return nil , errors .New ("config must not be nil" )
107107 }
@@ -117,11 +117,11 @@ func psiphonStartTunnel(ctx context.Context, config *DialerConfig) (psiphonTunne
117117 DisableLocalHTTPProxy : & trueValue ,
118118 }
119119
120- return clientlib .StartTunnel (ctx , config .ProviderConfig , "" , params , nil , nil )
120+ return clientlib .StartTunnel (tunnelCtx , config .ProviderConfig , "" , params , nil , nil )
121121}
122122
123123// Start configures and runs the Dialer. It must be called before you can use the Dialer. It returns when the tunnel is ready.
124- func (d * Dialer ) Start (ctx context.Context , config * DialerConfig ) error {
124+ func (d * Dialer ) Start (startCtx context.Context , config * DialerConfig ) error {
125125 resultCh := make (chan error )
126126 go func () {
127127 d .mu .Lock ()
@@ -132,13 +132,23 @@ func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
132132 return
133133 }
134134
135- ctx , cancel := context .WithCancel (ctx )
136- defer cancel ()
135+ // startCtx is intended for the lifetime of the startup.
136+ // dialerCtx is intended for the lifetime of the tunnel.
137+ dialerCtx , dialerCancel := context .WithCancel (context .Background ())
138+ defer dialerCancel ()
139+
140+ // This ties startCtx and dialerCtx together
141+ // so dialerCtx will be cancelled if startCtx is cancelled.
142+ // We run detatchContexts after startTunnel to disconnect them.
143+ detatchContexts := context .AfterFunc (startCtx , func () {
144+ dialerCancel ()
145+ })
146+
137147 tunnelDone := make (chan struct {})
138148 defer close (tunnelDone )
139149 d .stop = func () {
140150 // Tell start to stop.
141- cancel ()
151+ dialerCancel ()
142152 // Wait for tunnel to be done.
143153 <- tunnelDone
144154 }
@@ -148,13 +158,13 @@ func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
148158 }()
149159
150160 d .mu .Unlock ()
151-
152- tunnel , err := startTunnel (ctx , config )
161+ tunnel , err := startTunnel (dialerCtx , config )
153162
154163 d .mu .Lock ()
164+ detatchContexts ()
155165
156- if ctx .Err () != nil {
157- err = context .Cause (ctx )
166+ if dialerCtx .Err () != nil {
167+ err = context .Cause (dialerCtx )
158168 }
159169 if err != nil {
160170 resultCh <- err
@@ -169,7 +179,7 @@ func (d *Dialer) Start(ctx context.Context, config *DialerConfig) error {
169179
170180 d .mu .Unlock ()
171181 // wait for Stop
172- <- ctx .Done ()
182+ <- dialerCtx .Done ()
173183 d .mu .Lock ()
174184 }()
175185 return <- resultCh
0 commit comments