Compare commits

..

1 Commits

Author SHA1 Message Date
riccardom
051ed1efdc [client] Fix statemanager possible deadlock
1. Stop() takes m.mu.Lock() and defers m.mu.Unlock()
2. <-m.done under lock
3. periodicStateSave defers close(m.done)
4. periodicStateSave calls PersistState() (line 256) which does m.mu.Lock()

Double Stop() remains idempotent: second cancel() on dead ctx
 (no-op) and reads done already closed (immediate return).
2026-05-21 08:53:19 +02:00
2 changed files with 35 additions and 13 deletions

View File

@@ -96,17 +96,19 @@ func (m *Manager) Stop(ctx context.Context) error {
}
m.mu.Lock()
defer m.mu.Unlock()
cancel := m.cancel
done := m.done
m.mu.Unlock()
if m.cancel == nil {
if cancel == nil {
return nil
}
m.cancel()
cancel()
select {
case <-ctx.Done():
return ctx.Err()
case <-m.done:
case <-done:
}
return nil

View File

@@ -3,14 +3,15 @@
package system
import (
"bytes"
"context"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"time"
"golang.org/x/sys/unix"
log "github.com/sirupsen/logrus"
"github.com/zcalusic/sysinfo"
@@ -28,14 +29,19 @@ func UpdateStaticInfoAsync() {
// GetInfo retrieves and parses the system information
func GetInfo(ctx context.Context) *Info {
var uts unix.Utsname
if err := unix.Uname(&uts); err != nil {
return nil
info := _getInfo()
for strings.Contains(info, "broken pipe") {
info = _getInfo()
time.Sleep(500 * time.Millisecond)
}
osStr := strings.ReplaceAll(info, "\n", "")
osStr = strings.ReplaceAll(osStr, "\r\n", "")
osInfo := strings.Split(osStr, " ")
osName, osVersion := readOsReleaseFile()
if osName == "" {
osName = unix.ByteSliceToString(uts.Sysname[:])
osName = osInfo[3]
}
systemHostname, _ := os.Hostname()
@@ -52,8 +58,8 @@ func GetInfo(ctx context.Context) *Info {
}
gio := &Info{
Kernel: unix.ByteSliceToString(uts.Sysname[:]),
Platform: unix.ByteSliceToString(uts.Machine[:]),
Kernel: osInfo[0],
Platform: osInfo[2],
OS: osName,
OSVersion: osVersion,
Hostname: extractDeviceName(ctx, systemHostname),
@@ -61,7 +67,7 @@ func GetInfo(ctx context.Context) *Info {
CPUs: runtime.NumCPU(),
NetbirdVersion: version.NetbirdVersion(),
UIVersion: extractUserAgent(ctx),
KernelVersion: unix.ByteSliceToString(uts.Release[:]),
KernelVersion: osInfo[1],
NetworkAddresses: addrs,
SystemSerialNumber: si.SystemSerialNumber,
SystemProductName: si.SystemProductName,
@@ -72,6 +78,20 @@ func GetInfo(ctx context.Context) *Info {
return gio
}
func _getInfo() string {
cmd := exec.Command("uname", "-srio")
cmd.Stdin = strings.NewReader("some")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Warnf("getInfo: %s", err)
}
return out.String()
}
func sysInfo() (string, string, string) {
isascii := regexp.MustCompile("^[[:ascii:]]+$")
si := getSystemInfo()