mirror of https://github.com/jetkvm/kvm.git
fix deadlocks
This commit is contained in:
parent
45b55fe89f
commit
656df6c910
|
|
@ -3,6 +3,7 @@ package timesync
|
|||
import (
|
||||
"context"
|
||||
"math/rand/v2"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
|
@ -37,7 +38,47 @@ var DefaultNTPServerHostnames = []string{
|
|||
"pool.ntp.org",
|
||||
}
|
||||
|
||||
func (t *TimeSync) filterNTPServers(ntpServers []string) ([]string, error) {
|
||||
if len(ntpServers) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
hasIPv4, err := t.preCheckIPv4()
|
||||
if err != nil {
|
||||
t.l.Error().Err(err).Msg("failed to check IPv4")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasIPv6, err := t.preCheckIPv6()
|
||||
if err != nil {
|
||||
t.l.Error().Err(err).Msg("failed to check IPv6")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filteredServers := []string{}
|
||||
for _, server := range ntpServers {
|
||||
ip := net.ParseIP(server)
|
||||
t.l.Trace().Str("server", server).Interface("ip", ip).Msg("checking NTP server")
|
||||
if ip == nil {
|
||||
continue
|
||||
}
|
||||
if hasIPv4 && ip.To4() != nil {
|
||||
filteredServers = append(filteredServers, server)
|
||||
}
|
||||
if hasIPv6 && ip.To16() != nil {
|
||||
filteredServers = append(filteredServers, server)
|
||||
}
|
||||
}
|
||||
return filteredServers, nil
|
||||
}
|
||||
|
||||
func (t *TimeSync) queryNetworkTime(ntpServers []string) (now *time.Time, offset *time.Duration) {
|
||||
ntpServers, err := t.filterNTPServers(ntpServers)
|
||||
if err != nil {
|
||||
t.l.Error().Err(err).Msg("failed to filter NTP servers")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
chunkSize := int(t.networkConfig.TimeSyncParallel.ValueOr(4))
|
||||
t.l.Info().Strs("servers", ntpServers).Int("chunkSize", chunkSize).Msg("querying NTP servers")
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ var (
|
|||
timeSyncRetryInterval = 0 * time.Second
|
||||
)
|
||||
|
||||
type PreCheckFunc func() (bool, error)
|
||||
|
||||
type TimeSync struct {
|
||||
syncLock *sync.Mutex
|
||||
l *zerolog.Logger
|
||||
|
|
@ -37,11 +39,15 @@ type TimeSync struct {
|
|||
|
||||
syncSuccess bool
|
||||
|
||||
preCheckFunc func() (bool, error)
|
||||
preCheckFunc PreCheckFunc
|
||||
preCheckIPv4 PreCheckFunc
|
||||
preCheckIPv6 PreCheckFunc
|
||||
}
|
||||
|
||||
type TimeSyncOptions struct {
|
||||
PreCheckFunc func() (bool, error)
|
||||
PreCheckFunc PreCheckFunc
|
||||
PreCheckIPv4 PreCheckFunc
|
||||
PreCheckIPv6 PreCheckFunc
|
||||
Logger *zerolog.Logger
|
||||
NetworkConfig *types.NetworkConfig
|
||||
}
|
||||
|
|
@ -69,6 +75,8 @@ func NewTimeSync(opts *TimeSyncOptions) *TimeSync {
|
|||
rtcDevicePath: rtcDevice,
|
||||
rtcLock: &sync.Mutex{},
|
||||
preCheckFunc: opts.PreCheckFunc,
|
||||
preCheckIPv4: opts.PreCheckIPv4,
|
||||
preCheckIPv6: opts.PreCheckIPv6,
|
||||
networkConfig: opts.NetworkConfig,
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +120,13 @@ func (t *TimeSync) getSyncMode() SyncMode {
|
|||
}
|
||||
}
|
||||
|
||||
t.l.Debug().Strs("Ordering", syncMode.Ordering).Bool("Ntp", syncMode.Ntp).Bool("Http", syncMode.Http).Bool("NtpUseFallback", syncMode.NtpUseFallback).Bool("HttpUseFallback", syncMode.HttpUseFallback).Msg("sync mode")
|
||||
t.l.Debug().
|
||||
Strs("Ordering", syncMode.Ordering).
|
||||
Bool("Ntp", syncMode.Ntp).
|
||||
Bool("Http", syncMode.Http).
|
||||
Bool("NtpUseFallback", syncMode.NtpUseFallback).
|
||||
Bool("HttpUseFallback", syncMode.HttpUseFallback).
|
||||
Msg("sync mode")
|
||||
|
||||
return syncMode
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,30 +152,63 @@ func (im *InterfaceManager) link() (*link.Link, error) {
|
|||
|
||||
// IsUp returns true if the interface is up
|
||||
func (im *InterfaceManager) IsUp() bool {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.Up
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) IsOnline() bool {
|
||||
return im.IsUp()
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.Online
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) IPv4Ready() bool {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.IPv4Ready
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) IPv6Ready() bool {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.IPv6Ready
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) GetIPv4Addresses() []string {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.IPv4Addresses
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) GetIPv4Address() string {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.IPv4Address
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) GetIPv6Address() string {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
return im.state.IPv6Address
|
||||
}
|
||||
|
||||
func (im *InterfaceManager) GetIPv6Addresses() []string {
|
||||
im.stateMu.RLock()
|
||||
defer im.stateMu.RUnlock()
|
||||
|
||||
addresses := []string{}
|
||||
for _, addr := range im.state.IPv6Addresses {
|
||||
addresses = append(addresses, addr.Address.String())
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
|
|
@ -569,11 +602,11 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
|||
hasAddrs = true
|
||||
}
|
||||
|
||||
im.stateMu.Lock()
|
||||
defer im.stateMu.Unlock()
|
||||
|
||||
// Check if state changed
|
||||
stateChanged := false
|
||||
// We should release the lock before calling the callbacks
|
||||
// to avoid deadlocks
|
||||
im.stateMu.Lock()
|
||||
if im.state.Up != isUp {
|
||||
im.state.Up = isUp
|
||||
stateChanged = true
|
||||
|
|
@ -594,6 +627,7 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
|||
}
|
||||
|
||||
im.state.LastUpdated = time.Now()
|
||||
im.stateMu.Unlock()
|
||||
|
||||
// Notify callback if state changed
|
||||
if stateChanged && im.onStateChange != nil {
|
||||
|
|
@ -661,9 +695,8 @@ func (im *InterfaceManager) updateIPAddresses(nl *link.Link) error {
|
|||
// updateStateFromDHCPLease updates the state from a DHCP lease
|
||||
func (im *InterfaceManager) updateStateFromDHCPLease(lease *types.DHCPLease) {
|
||||
im.stateMu.Lock()
|
||||
defer im.stateMu.Unlock()
|
||||
|
||||
im.state.DHCPLease4 = lease
|
||||
im.stateMu.Unlock()
|
||||
|
||||
// Update resolv.conf with DNS information
|
||||
if im.resolvConf != nil {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@ func (nm *NetworkManager) IsOnline() bool {
|
|||
}
|
||||
|
||||
func (nm *NetworkManager) IsUp() bool {
|
||||
return nm.IsOnline()
|
||||
for _, iface := range nm.interfaces {
|
||||
if iface.IsUp() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (nm *NetworkManager) GetHostname() string {
|
||||
|
|
@ -74,6 +79,20 @@ func (nm *NetworkManager) GetMACAddress() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (nm *NetworkManager) IPv4Ready() bool {
|
||||
for _, iface := range nm.interfaces {
|
||||
return iface.IPv4Ready()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (nm *NetworkManager) IPv6Ready() bool {
|
||||
for _, iface := range nm.interfaces {
|
||||
return iface.IPv6Ready()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (nm *NetworkManager) IPv4String() string {
|
||||
return nm.GetIPv4Address()
|
||||
}
|
||||
|
|
|
|||
12
timesync.go
12
timesync.go
|
|
@ -43,6 +43,18 @@ func initTimeSync() {
|
|||
timeSync = timesync.NewTimeSync(×ync.TimeSyncOptions{
|
||||
Logger: timesyncLogger,
|
||||
NetworkConfig: config.NetworkConfig,
|
||||
PreCheckIPv4: func() (bool, error) {
|
||||
if !networkManager.IPv4Ready() {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
PreCheckIPv6: func() (bool, error) {
|
||||
if !networkManager.IPv6Ready() {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
PreCheckFunc: func() (bool, error) {
|
||||
if !networkManager.IsOnline() {
|
||||
return false, nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue