Skip to content

Commit d0fe309

Browse files
committed
Fix ssh shutdown deadlock
1 parent 7c88788 commit d0fe309

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

client/internal/engine.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ type Engine struct {
148148

149149
// syncMsgMux is used to guarantee sequential Management Service message processing
150150
syncMsgMux *sync.Mutex
151+
// sshMux protects sshServer field access
152+
sshMux sync.Mutex
151153

152154
config *EngineConfig
153155
mobileDep MobileDependency
@@ -710,9 +712,11 @@ func (e *Engine) removeAllPeers() error {
710712
func (e *Engine) removePeer(peerKey string) error {
711713
log.Debugf("removing peer from engine %s", peerKey)
712714

715+
e.sshMux.Lock()
713716
if !isNil(e.sshServer) {
714717
e.sshServer.RemoveAuthorizedKey(peerKey)
715718
}
719+
e.sshMux.Unlock()
716720

717721
e.connMgr.RemovePeerConn(peerKey)
718722

@@ -914,6 +918,7 @@ func (e *Engine) updateSSH(sshConf *mgmProto.SSHConfig) error {
914918
log.Warnf("running SSH server on %s is not supported", runtime.GOOS)
915919
return nil
916920
}
921+
e.sshMux.Lock()
917922
// start SSH server if it wasn't running
918923
if isNil(e.sshServer) {
919924
listenAddr := fmt.Sprintf("%s:%d", e.wgInterface.Address().IP.String(), nbssh.DefaultSSHPort)
@@ -925,32 +930,37 @@ func (e *Engine) updateSSH(sshConf *mgmProto.SSHConfig) error {
925930
e.sshServer, err = e.sshServerFunc(e.config.SSHKey, listenAddr)
926931

927932
if err != nil {
933+
e.sshMux.Unlock()
928934
return fmt.Errorf("create ssh server: %w", err)
929935
}
930-
e.shutdownWg.Add(1)
936+
e.sshMux.Unlock()
931937
go func() {
932-
defer e.shutdownWg.Done()
933938
// blocking
934939
err = e.sshServer.Start()
935940
if err != nil {
936941
// will throw error when we stop it even if it is a graceful stop
937942
log.Debugf("stopped SSH server with error %v", err)
938943
}
939-
e.syncMsgMux.Lock()
940-
defer e.syncMsgMux.Unlock()
944+
e.sshMux.Lock()
941945
e.sshServer = nil
946+
e.sshMux.Unlock()
942947
log.Infof("stopped SSH server")
943948
}()
944949
} else {
950+
e.sshMux.Unlock()
945951
log.Debugf("SSH server is already running")
946952
}
947-
} else if !isNil(e.sshServer) {
948-
// Disable SSH server request, so stop it if it was running
949-
err := e.sshServer.Stop()
950-
if err != nil {
951-
log.Warnf("failed to stop SSH server %v", err)
953+
} else {
954+
e.sshMux.Lock()
955+
if !isNil(e.sshServer) {
956+
// Disable SSH server request, so stop it if it was running
957+
err := e.sshServer.Stop()
958+
if err != nil {
959+
log.Warnf("failed to stop SSH server %v", err)
960+
}
961+
e.sshServer = nil
952962
}
953-
e.sshServer = nil
963+
e.sshMux.Unlock()
954964
}
955965
return nil
956966
}
@@ -1165,6 +1175,7 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
11651175
e.statusRecorder.FinishPeerListModifications()
11661176

11671177
// update SSHServer by adding remote peer SSH keys
1178+
e.sshMux.Lock()
11681179
if !isNil(e.sshServer) {
11691180
for _, config := range networkMap.GetRemotePeers() {
11701181
if config.GetSshConfig() != nil && config.GetSshConfig().GetSshPubKey() != nil {
@@ -1175,6 +1186,7 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
11751186
}
11761187
}
11771188
}
1189+
e.sshMux.Unlock()
11781190
}
11791191

11801192
// must set the exclude list after the peers are added. Without it the manager can not figure out the peers parameters from the store
@@ -1536,12 +1548,14 @@ func (e *Engine) close() {
15361548
e.statusRecorder.SetWgIface(nil)
15371549
}
15381550

1551+
e.sshMux.Lock()
15391552
if !isNil(e.sshServer) {
15401553
err := e.sshServer.Stop()
15411554
if err != nil {
15421555
log.Warnf("failed stopping the SSH server: %v", err)
15431556
}
15441557
}
1558+
e.sshMux.Unlock()
15451559

15461560
if e.firewall != nil {
15471561
err := e.firewall.Close(e.stateManager)

0 commit comments

Comments
 (0)