Skip to content

Commit 7120141

Browse files
authored
fix(portforward): rework run loop and fix deadlocks (#1874)
1 parent c435bbb commit 7120141

30 files changed

+453
-476
lines changed

cmd/gluetun/main.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,7 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
377377
portForwardLogger := logger.New(log.SetComponent("port forwarding"))
378378
portForwardLooper := portforward.NewLoop(allSettings.VPN.Provider.PortForwarding,
379379
httpClient, firewallConf, portForwardLogger, puid, pgid)
380-
portForwardHandler, portForwardCtx, portForwardDone := goshutdown.NewGoRoutineHandler(
381-
"port forwarding", goroutine.OptionTimeout(time.Second))
382-
go portForwardLooper.Run(portForwardCtx, portForwardDone)
380+
portForwardRunError, _ := portForwardLooper.Start(context.Background())
383381

384382
unboundLogger := logger.New(log.SetComponent("dns"))
385383
unboundLooper := dns.NewLoop(dnsConf, allSettings.DNS, httpClient,
@@ -481,13 +479,21 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
481479
order.OptionOnSuccess(defaultShutdownOnSuccess),
482480
order.OptionOnFailure(defaultShutdownOnFailure))
483481
orderHandler.Append(controlGroupHandler, tickersGroupHandler, healthServerHandler,
484-
vpnHandler, portForwardHandler, otherGroupHandler)
482+
vpnHandler, otherGroupHandler)
485483

486484
// Start VPN for the first time in a blocking call
487485
// until the VPN is launched
488486
_, _ = vpnLooper.ApplyStatus(ctx, constants.Running) // TODO option to disable with variable
489487

490-
<-ctx.Done()
488+
select {
489+
case <-ctx.Done():
490+
err = portForwardLooper.Stop()
491+
if err != nil {
492+
logger.Error("stopping port forward loop: " + err.Error())
493+
}
494+
case err := <-portForwardRunError:
495+
logger.Errorf("port forwarding loop crashed: %s", err)
496+
}
491497

492498
return orderHandler.Shutdown(context.Background())
493499
}

internal/configuration/settings/portforward.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type PortForwarding struct {
3030
Filepath *string `json:"status_file_path"`
3131
}
3232

33-
func (p PortForwarding) validate(vpnProvider string) (err error) {
33+
func (p PortForwarding) Validate(vpnProvider string) (err error) {
3434
if !*p.Enabled {
3535
return nil
3636
}
@@ -59,7 +59,7 @@ func (p PortForwarding) validate(vpnProvider string) (err error) {
5959
return nil
6060
}
6161

62-
func (p *PortForwarding) copy() (copied PortForwarding) {
62+
func (p *PortForwarding) Copy() (copied PortForwarding) {
6363
return PortForwarding{
6464
Enabled: gosettings.CopyPointer(p.Enabled),
6565
Provider: gosettings.CopyPointer(p.Provider),
@@ -73,7 +73,7 @@ func (p *PortForwarding) mergeWith(other PortForwarding) {
7373
p.Filepath = gosettings.MergeWithPointer(p.Filepath, other.Filepath)
7474
}
7575

76-
func (p *PortForwarding) overrideWith(other PortForwarding) {
76+
func (p *PortForwarding) OverrideWith(other PortForwarding) {
7777
p.Enabled = gosettings.OverrideWithPointer(p.Enabled, other.Enabled)
7878
p.Provider = gosettings.OverrideWithPointer(p.Provider, other.Provider)
7979
p.Filepath = gosettings.OverrideWithPointer(p.Filepath, other.Filepath)

internal/configuration/settings/provider.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (p *Provider) validate(vpnType string, storage Storage) (err error) {
4949
return fmt.Errorf("server selection: %w", err)
5050
}
5151

52-
err = p.PortForwarding.validate(*p.Name)
52+
err = p.PortForwarding.Validate(*p.Name)
5353
if err != nil {
5454
return fmt.Errorf("port forwarding: %w", err)
5555
}
@@ -61,7 +61,7 @@ func (p *Provider) copy() (copied Provider) {
6161
return Provider{
6262
Name: gosettings.CopyPointer(p.Name),
6363
ServerSelection: p.ServerSelection.copy(),
64-
PortForwarding: p.PortForwarding.copy(),
64+
PortForwarding: p.PortForwarding.Copy(),
6565
}
6666
}
6767

@@ -74,7 +74,7 @@ func (p *Provider) mergeWith(other Provider) {
7474
func (p *Provider) overrideWith(other Provider) {
7575
p.Name = gosettings.OverrideWithPointer(p.Name, other.Name)
7676
p.ServerSelection.overrideWith(other.ServerSelection)
77-
p.PortForwarding.overrideWith(other.PortForwarding)
77+
p.PortForwarding.OverrideWith(other.PortForwarding)
7878
}
7979

8080
func (p *Provider) setDefaults() {

internal/portforward/firewall.go

-32
This file was deleted.

internal/portforward/fs.go

-37
This file was deleted.

internal/portforward/get.go

-5
This file was deleted.

internal/portforward/helpers.go

-22
This file was deleted.

internal/portforward/interfaces.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
package portforward
22

3-
import (
4-
"context"
5-
)
3+
import "context"
4+
5+
type Service interface {
6+
Start(ctx context.Context) (runError <-chan error, err error)
7+
Stop() (err error)
8+
GetPortForwarded() (port uint16)
9+
}
610

711
type PortAllower interface {
812
SetAllowedPort(ctx context.Context, port uint16, intf string) (err error)
913
RemoveAllowedPort(ctx context.Context, port uint16) (err error)
1014
}
15+
16+
type Logger interface {
17+
Info(s string)
18+
Warn(s string)
19+
Error(s string)
20+
}

internal/portforward/logger.go

-7
This file was deleted.

0 commit comments

Comments
 (0)