From ded635bd566e29a3a55d5e1f1d650828eb9766fc Mon Sep 17 00:00:00 2001 From: "Quentin McGaw (desktop)" Date: Thu, 13 Feb 2020 13:23:22 +0000 Subject: [PATCH] Fatal container exit if openvpn or unbound exits --- cmd/main.go | 24 +++++++++++++++++++----- internal/dns/command.go | 6 +++--- internal/dns/command_test.go | 3 ++- internal/dns/dns.go | 2 +- internal/openvpn/command.go | 6 +++--- internal/openvpn/openvpn.go | 2 +- internal/shadowsocks/command.go | 6 +++--- internal/shadowsocks/shadowsocks.go | 2 +- internal/tinyproxy/command.go | 6 +++--- internal/tinyproxy/tinyproxy.go | 2 +- 10 files changed, 37 insertions(+), 22 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 027616667..2540c796e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -102,8 +102,11 @@ func main() { e.FatalOnError(err) err = dnsConf.MakeUnboundConf(allSettings.DNS, uid, gid) e.FatalOnError(err) - stream, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel) + stream, waitFn, err := dnsConf.Start(allSettings.DNS.VerbosityDetailsLevel) e.FatalOnError(err) + go func() { + e.FatalOnError(waitFn()) + }() go streamMerger.Merge("unbound", stream) dnsConf.UseDNSInternally(net.IP{127, 0, 0, 1}) // use Unbound err = dnsConf.UseDNSSystemWide(net.IP{127, 0, 0, 1}) // use Unbound @@ -133,16 +136,26 @@ func main() { if allSettings.TinyProxy.Enabled { err = tinyProxyConf.MakeConf(allSettings.TinyProxy.LogLevel, allSettings.TinyProxy.Port, allSettings.TinyProxy.User, allSettings.TinyProxy.Password, uid, gid) e.FatalOnError(err) - stream, err := tinyProxyConf.Start() + stream, waitFn, err := tinyProxyConf.Start() e.FatalOnError(err) + go func() { + if err := waitFn(); err != nil { + logger.Error(err) + } + }() go streamMerger.Merge("tinyproxy", stream) } if allSettings.ShadowSocks.Enabled { err = shadowsocksConf.MakeConf(allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, uid, gid) e.FatalOnError(err) - stream, err := shadowsocksConf.Start("0.0.0.0", allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, allSettings.ShadowSocks.Log) + stream, waitFn, err := shadowsocksConf.Start("0.0.0.0", allSettings.ShadowSocks.Port, allSettings.ShadowSocks.Password, allSettings.ShadowSocks.Log) e.FatalOnError(err) + go func() { + if err := waitFn(); err != nil { + logger.Error(err) + } + }() go streamMerger.Merge("shadowsocks", stream) } @@ -161,12 +174,13 @@ func main() { }) } - stream, err := ovpnConf.Start() + stream, waitFn, err := ovpnConf.Start() e.FatalOnError(err) go streamMerger.Merge("openvpn", stream) - signals.WaitForExit(func(signal string) int { + go signals.WaitForExit(func(signal string) int { logger.Warn("Caught OS signal %s, shutting down", signal) time.Sleep(100 * time.Millisecond) // wait for other processes to exit return 0 }) + e.FatalOnError(waitFn()) } diff --git a/internal/dns/command.go b/internal/dns/command.go index 42c68d7af..232e7cc7d 100644 --- a/internal/dns/command.go +++ b/internal/dns/command.go @@ -8,15 +8,15 @@ import ( "github.com/qdm12/private-internet-access-docker/internal/constants" ) -func (c *configurator) Start(verbosityDetailsLevel uint8) (stdout io.ReadCloser, err error) { +func (c *configurator) Start(verbosityDetailsLevel uint8) (stdout io.ReadCloser, waitFn func() error, err error) { c.logger.Info("%s: starting unbound", logPrefix) args := []string{"-d", "-c", string(constants.UnboundConf)} if verbosityDetailsLevel > 0 { args = append(args, "-"+strings.Repeat("v", int(verbosityDetailsLevel))) } // Only logs to stderr - _, stdout, _, err = c.commander.Start("unbound", args...) - return stdout, err + _, stdout, waitFn, err = c.commander.Start("unbound", args...) + return stdout, waitFn, err } func (c *configurator) Version() (version string, err error) { diff --git a/internal/dns/command_test.go b/internal/dns/command_test.go index e230c849f..495ee5ae6 100644 --- a/internal/dns/command_test.go +++ b/internal/dns/command_test.go @@ -20,8 +20,9 @@ func Test_Start(t *testing.T) { commander.On("Start", "unbound", "-d", "-c", string(constants.UnboundConf), "-vv"). Return(nil, nil, nil, nil).Once() c := &configurator{commander: commander, logger: logger} - stdout, err := c.Start(2) + stdout, waitFn, err := c.Start(2) assert.Nil(t, stdout) + assert.Nil(t, waitFn) assert.NoError(t, err) logger.AssertExpectations(t) commander.AssertExpectations(t) diff --git a/internal/dns/dns.go b/internal/dns/dns.go index f2d521598..47d6a8584 100644 --- a/internal/dns/dns.go +++ b/internal/dns/dns.go @@ -19,7 +19,7 @@ type Configurator interface { MakeUnboundConf(settings settings.DNS, uid, gid int) (err error) UseDNSInternally(IP net.IP) UseDNSSystemWide(IP net.IP) error - Start(logLevel uint8) (stdout io.ReadCloser, err error) + Start(logLevel uint8) (stdout io.ReadCloser, waitFn func() error, err error) WaitForUnbound() (err error) Version() (version string, err error) } diff --git a/internal/openvpn/command.go b/internal/openvpn/command.go index 947c86c30..3081d2545 100644 --- a/internal/openvpn/command.go +++ b/internal/openvpn/command.go @@ -8,10 +8,10 @@ import ( "github.com/qdm12/private-internet-access-docker/internal/constants" ) -func (c *configurator) Start() (stdout io.ReadCloser, err error) { +func (c *configurator) Start() (stdout io.ReadCloser, waitFn func() error, err error) { c.logger.Info("%s: starting openvpn", logPrefix) - stdout, _, _, err = c.commander.Start("openvpn", "--config", string(constants.OpenVPNConf)) - return stdout, err + stdout, _, waitFn, err = c.commander.Start("openvpn", "--config", string(constants.OpenVPNConf)) + return stdout, waitFn, err } func (c *configurator) Version() (string, error) { diff --git a/internal/openvpn/openvpn.go b/internal/openvpn/openvpn.go index ee3d47307..56ff38bec 100644 --- a/internal/openvpn/openvpn.go +++ b/internal/openvpn/openvpn.go @@ -17,7 +17,7 @@ type Configurator interface { WriteAuthFile(user, password string, uid, gid int) error CheckTUN() error CreateTUN() error - Start() (stdout io.ReadCloser, err error) + Start() (stdout io.ReadCloser, waitFn func() error, err error) } type configurator struct { diff --git a/internal/shadowsocks/command.go b/internal/shadowsocks/command.go index 9684e63d8..23f32f09f 100644 --- a/internal/shadowsocks/command.go +++ b/internal/shadowsocks/command.go @@ -8,7 +8,7 @@ import ( "github.com/qdm12/private-internet-access-docker/internal/constants" ) -func (c *configurator) Start(server string, port uint16, password string, log bool) (stdout io.ReadCloser, err error) { +func (c *configurator) Start(server string, port uint16, password string, log bool) (stdout io.ReadCloser, waitFn func() error, err error) { c.logger.Info("%s: starting shadowsocks server", logPrefix) args := []string{ "-c", string(constants.ShadowsocksConf), @@ -18,8 +18,8 @@ func (c *configurator) Start(server string, port uint16, password string, log bo if log { args = append(args, "-v") } - stdout, _, _, err = c.commander.Start("ss-server", args...) - return stdout, err + stdout, _, waitFn, err = c.commander.Start("ss-server", args...) + return stdout, waitFn, err } // Version obtains the version of the installed shadowsocks server diff --git a/internal/shadowsocks/shadowsocks.go b/internal/shadowsocks/shadowsocks.go index 52241128d..3b5860b47 100644 --- a/internal/shadowsocks/shadowsocks.go +++ b/internal/shadowsocks/shadowsocks.go @@ -13,7 +13,7 @@ const logPrefix = "shadowsocks configurator" type Configurator interface { Version() (string, error) MakeConf(port uint16, password string, uid, gid int) (err error) - Start(server string, port uint16, password string, log bool) (stdout io.ReadCloser, err error) + Start(server string, port uint16, password string, log bool) (stdout io.ReadCloser, waitFn func() error, err error) } type configurator struct { diff --git a/internal/tinyproxy/command.go b/internal/tinyproxy/command.go index 15786e280..176a1ece5 100644 --- a/internal/tinyproxy/command.go +++ b/internal/tinyproxy/command.go @@ -6,10 +6,10 @@ import ( "strings" ) -func (c *configurator) Start() (stdout io.ReadCloser, err error) { +func (c *configurator) Start() (stdout io.ReadCloser, waitFn func() error, err error) { c.logger.Info("%s: starting tinyproxy server", logPrefix) - stdout, _, _, err = c.commander.Start("tinyproxy", "-d") - return stdout, err + stdout, _, waitFn, err = c.commander.Start("tinyproxy", "-d") + return stdout, waitFn, err } // Version obtains the version of the installed Tinyproxy server diff --git a/internal/tinyproxy/tinyproxy.go b/internal/tinyproxy/tinyproxy.go index 663389a05..1fd206381 100644 --- a/internal/tinyproxy/tinyproxy.go +++ b/internal/tinyproxy/tinyproxy.go @@ -14,7 +14,7 @@ const logPrefix = "tinyproxy configurator" type Configurator interface { Version() (string, error) MakeConf(logLevel models.TinyProxyLogLevel, port uint16, user, password string, uid, gid int) error - Start() (stdout io.ReadCloser, err error) + Start() (stdout io.ReadCloser, waitFn func() error, err error) } type configurator struct {