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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -37,7 +38,47 @@ var DefaultNTPServerHostnames = []string{
|
||||||
"pool.ntp.org",
|
"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) {
|
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))
|
chunkSize := int(t.networkConfig.TimeSyncParallel.ValueOr(4))
|
||||||
t.l.Info().Strs("servers", ntpServers).Int("chunkSize", chunkSize).Msg("querying NTP servers")
|
t.l.Info().Strs("servers", ntpServers).Int("chunkSize", chunkSize).Msg("querying NTP servers")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ var (
|
||||||
timeSyncRetryInterval = 0 * time.Second
|
timeSyncRetryInterval = 0 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PreCheckFunc func() (bool, error)
|
||||||
|
|
||||||
type TimeSync struct {
|
type TimeSync struct {
|
||||||
syncLock *sync.Mutex
|
syncLock *sync.Mutex
|
||||||
l *zerolog.Logger
|
l *zerolog.Logger
|
||||||
|
|
@ -37,11 +39,15 @@ type TimeSync struct {
|
||||||
|
|
||||||
syncSuccess bool
|
syncSuccess bool
|
||||||
|
|
||||||
preCheckFunc func() (bool, error)
|
preCheckFunc PreCheckFunc
|
||||||
|
preCheckIPv4 PreCheckFunc
|
||||||
|
preCheckIPv6 PreCheckFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
type TimeSyncOptions struct {
|
type TimeSyncOptions struct {
|
||||||
PreCheckFunc func() (bool, error)
|
PreCheckFunc PreCheckFunc
|
||||||
|
PreCheckIPv4 PreCheckFunc
|
||||||
|
PreCheckIPv6 PreCheckFunc
|
||||||
Logger *zerolog.Logger
|
Logger *zerolog.Logger
|
||||||
NetworkConfig *types.NetworkConfig
|
NetworkConfig *types.NetworkConfig
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +75,8 @@ func NewTimeSync(opts *TimeSyncOptions) *TimeSync {
|
||||||
rtcDevicePath: rtcDevice,
|
rtcDevicePath: rtcDevice,
|
||||||
rtcLock: &sync.Mutex{},
|
rtcLock: &sync.Mutex{},
|
||||||
preCheckFunc: opts.PreCheckFunc,
|
preCheckFunc: opts.PreCheckFunc,
|
||||||
|
preCheckIPv4: opts.PreCheckIPv4,
|
||||||
|
preCheckIPv6: opts.PreCheckIPv6,
|
||||||
networkConfig: opts.NetworkConfig,
|
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
|
return syncMode
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,30 +152,63 @@ func (im *InterfaceManager) link() (*link.Link, error) {
|
||||||
|
|
||||||
// IsUp returns true if the interface is up
|
// IsUp returns true if the interface is up
|
||||||
func (im *InterfaceManager) IsUp() bool {
|
func (im *InterfaceManager) IsUp() bool {
|
||||||
|
im.stateMu.RLock()
|
||||||
|
defer im.stateMu.RUnlock()
|
||||||
|
|
||||||
return im.state.Up
|
return im.state.Up
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *InterfaceManager) IsOnline() bool {
|
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 {
|
func (im *InterfaceManager) GetIPv4Addresses() []string {
|
||||||
|
im.stateMu.RLock()
|
||||||
|
defer im.stateMu.RUnlock()
|
||||||
|
|
||||||
return im.state.IPv4Addresses
|
return im.state.IPv4Addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *InterfaceManager) GetIPv4Address() string {
|
func (im *InterfaceManager) GetIPv4Address() string {
|
||||||
|
im.stateMu.RLock()
|
||||||
|
defer im.stateMu.RUnlock()
|
||||||
|
|
||||||
return im.state.IPv4Address
|
return im.state.IPv4Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *InterfaceManager) GetIPv6Address() string {
|
func (im *InterfaceManager) GetIPv6Address() string {
|
||||||
|
im.stateMu.RLock()
|
||||||
|
defer im.stateMu.RUnlock()
|
||||||
|
|
||||||
return im.state.IPv6Address
|
return im.state.IPv6Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *InterfaceManager) GetIPv6Addresses() []string {
|
func (im *InterfaceManager) GetIPv6Addresses() []string {
|
||||||
|
im.stateMu.RLock()
|
||||||
|
defer im.stateMu.RUnlock()
|
||||||
|
|
||||||
addresses := []string{}
|
addresses := []string{}
|
||||||
for _, addr := range im.state.IPv6Addresses {
|
for _, addr := range im.state.IPv6Addresses {
|
||||||
addresses = append(addresses, addr.Address.String())
|
addresses = append(addresses, addr.Address.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -569,11 +602,11 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
||||||
hasAddrs = true
|
hasAddrs = true
|
||||||
}
|
}
|
||||||
|
|
||||||
im.stateMu.Lock()
|
|
||||||
defer im.stateMu.Unlock()
|
|
||||||
|
|
||||||
// Check if state changed
|
// Check if state changed
|
||||||
stateChanged := false
|
stateChanged := false
|
||||||
|
// We should release the lock before calling the callbacks
|
||||||
|
// to avoid deadlocks
|
||||||
|
im.stateMu.Lock()
|
||||||
if im.state.Up != isUp {
|
if im.state.Up != isUp {
|
||||||
im.state.Up = isUp
|
im.state.Up = isUp
|
||||||
stateChanged = true
|
stateChanged = true
|
||||||
|
|
@ -594,6 +627,7 @@ func (im *InterfaceManager) updateInterfaceState() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
im.state.LastUpdated = time.Now()
|
im.state.LastUpdated = time.Now()
|
||||||
|
im.stateMu.Unlock()
|
||||||
|
|
||||||
// Notify callback if state changed
|
// Notify callback if state changed
|
||||||
if stateChanged && im.onStateChange != nil {
|
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
|
// updateStateFromDHCPLease updates the state from a DHCP lease
|
||||||
func (im *InterfaceManager) updateStateFromDHCPLease(lease *types.DHCPLease) {
|
func (im *InterfaceManager) updateStateFromDHCPLease(lease *types.DHCPLease) {
|
||||||
im.stateMu.Lock()
|
im.stateMu.Lock()
|
||||||
defer im.stateMu.Unlock()
|
|
||||||
|
|
||||||
im.state.DHCPLease4 = lease
|
im.state.DHCPLease4 = lease
|
||||||
|
im.stateMu.Unlock()
|
||||||
|
|
||||||
// Update resolv.conf with DNS information
|
// Update resolv.conf with DNS information
|
||||||
if im.resolvConf != nil {
|
if im.resolvConf != nil {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,12 @@ func (nm *NetworkManager) IsOnline() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nm *NetworkManager) IsUp() 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 {
|
func (nm *NetworkManager) GetHostname() string {
|
||||||
|
|
@ -74,6 +79,20 @@ func (nm *NetworkManager) GetMACAddress() string {
|
||||||
return ""
|
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 {
|
func (nm *NetworkManager) IPv4String() string {
|
||||||
return nm.GetIPv4Address()
|
return nm.GetIPv4Address()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
timesync.go
12
timesync.go
|
|
@ -43,6 +43,18 @@ func initTimeSync() {
|
||||||
timeSync = timesync.NewTimeSync(×ync.TimeSyncOptions{
|
timeSync = timesync.NewTimeSync(×ync.TimeSyncOptions{
|
||||||
Logger: timesyncLogger,
|
Logger: timesyncLogger,
|
||||||
NetworkConfig: config.NetworkConfig,
|
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) {
|
PreCheckFunc: func() (bool, error) {
|
||||||
if !networkManager.IsOnline() {
|
if !networkManager.IsOnline() {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue