mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Do not copy tcpip.CancellableTimer
A CancellableTimer's AfterFunc timer instance creates a closure over the CancellableTimer's address. This closure makes a CancellableTimer unsafe to copy. No behaviour change, existing tests pass. PiperOrigin-RevId: 308306664
This commit is contained in:
committed by
gVisor bot
parent
632b104aff
commit
1ceee04529
+21
-10
@@ -412,20 +412,33 @@ type dadState struct {
|
||||
// defaultRouterState holds data associated with a default router discovered by
|
||||
// a Router Advertisement (RA).
|
||||
type defaultRouterState struct {
|
||||
invalidationTimer tcpip.CancellableTimer
|
||||
// Timer to invalidate the default router.
|
||||
//
|
||||
// May not be nil.
|
||||
invalidationTimer *tcpip.CancellableTimer
|
||||
}
|
||||
|
||||
// onLinkPrefixState holds data associated with an on-link prefix discovered by
|
||||
// a Router Advertisement's Prefix Information option (PI) when the NDP
|
||||
// configurations was configured to do so.
|
||||
type onLinkPrefixState struct {
|
||||
invalidationTimer tcpip.CancellableTimer
|
||||
// Timer to invalidate the on-link prefix.
|
||||
//
|
||||
// May not be nil.
|
||||
invalidationTimer *tcpip.CancellableTimer
|
||||
}
|
||||
|
||||
// slaacPrefixState holds state associated with a SLAAC prefix.
|
||||
type slaacPrefixState struct {
|
||||
deprecationTimer tcpip.CancellableTimer
|
||||
invalidationTimer tcpip.CancellableTimer
|
||||
// Timer to deprecate the prefix.
|
||||
//
|
||||
// May not be nil.
|
||||
deprecationTimer *tcpip.CancellableTimer
|
||||
|
||||
// Timer to invalidate the prefix.
|
||||
//
|
||||
// May not be nil.
|
||||
invalidationTimer *tcpip.CancellableTimer
|
||||
|
||||
// Nonzero only when the address is not valid forever.
|
||||
validUntil time.Time
|
||||
@@ -775,7 +788,6 @@ func (ndp *ndpState) invalidateDefaultRouter(ip tcpip.Address) {
|
||||
}
|
||||
|
||||
rtr.invalidationTimer.StopLocked()
|
||||
|
||||
delete(ndp.defaultRouters, ip)
|
||||
|
||||
// Let the integrator know a discovered default router is invalidated.
|
||||
@@ -804,7 +816,7 @@ func (ndp *ndpState) rememberDefaultRouter(ip tcpip.Address, rl time.Duration) {
|
||||
}
|
||||
|
||||
state := defaultRouterState{
|
||||
invalidationTimer: tcpip.MakeCancellableTimer(&ndp.nic.mu, func() {
|
||||
invalidationTimer: tcpip.NewCancellableTimer(&ndp.nic.mu, func() {
|
||||
ndp.invalidateDefaultRouter(ip)
|
||||
}),
|
||||
}
|
||||
@@ -834,7 +846,7 @@ func (ndp *ndpState) rememberOnLinkPrefix(prefix tcpip.Subnet, l time.Duration)
|
||||
}
|
||||
|
||||
state := onLinkPrefixState{
|
||||
invalidationTimer: tcpip.MakeCancellableTimer(&ndp.nic.mu, func() {
|
||||
invalidationTimer: tcpip.NewCancellableTimer(&ndp.nic.mu, func() {
|
||||
ndp.invalidateOnLinkPrefix(prefix)
|
||||
}),
|
||||
}
|
||||
@@ -859,7 +871,6 @@ func (ndp *ndpState) invalidateOnLinkPrefix(prefix tcpip.Subnet) {
|
||||
}
|
||||
|
||||
s.invalidationTimer.StopLocked()
|
||||
|
||||
delete(ndp.onLinkPrefixes, prefix)
|
||||
|
||||
// Let the integrator know a discovered on-link prefix is invalidated.
|
||||
@@ -979,7 +990,7 @@ func (ndp *ndpState) doSLAAC(prefix tcpip.Subnet, pl, vl time.Duration) {
|
||||
}
|
||||
|
||||
state := slaacPrefixState{
|
||||
deprecationTimer: tcpip.MakeCancellableTimer(&ndp.nic.mu, func() {
|
||||
deprecationTimer: tcpip.NewCancellableTimer(&ndp.nic.mu, func() {
|
||||
state, ok := ndp.slaacPrefixes[prefix]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for the deprecated SLAAC prefix %s", prefix))
|
||||
@@ -987,7 +998,7 @@ func (ndp *ndpState) doSLAAC(prefix tcpip.Subnet, pl, vl time.Duration) {
|
||||
|
||||
ndp.deprecateSLAACAddress(state.ref)
|
||||
}),
|
||||
invalidationTimer: tcpip.MakeCancellableTimer(&ndp.nic.mu, func() {
|
||||
invalidationTimer: tcpip.NewCancellableTimer(&ndp.nic.mu, func() {
|
||||
state, ok := ndp.slaacPrefixes[prefix]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("ndp: must have a slaacPrefixes entry for the invalidated SLAAC prefix %s", prefix))
|
||||
|
||||
+22
-3
@@ -88,6 +88,9 @@ func (t *cancellableTimerInstance) stop() {
|
||||
//
|
||||
// The term "related work" is defined as some work that needs to be done while
|
||||
// holding some lock that the timer must also hold while doing some work.
|
||||
//
|
||||
// Note, it is not safe to copy a CancellableTimer as its timer instance creates
|
||||
// a closure over the address of the CancellableTimer.
|
||||
type CancellableTimer struct {
|
||||
// The active instance of a cancellable timer.
|
||||
instance cancellableTimerInstance
|
||||
@@ -154,12 +157,28 @@ func (t *CancellableTimer) Reset(d time.Duration) {
|
||||
}
|
||||
}
|
||||
|
||||
// MakeCancellableTimer returns an unscheduled CancellableTimer with the given
|
||||
// Lock is a no-op used by the copylocks checker from go vet.
|
||||
//
|
||||
// See CancellableTimer for details about why it shouldn't be copied.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/8005#issuecomment-190753527 for more
|
||||
// details about the copylocks checker.
|
||||
func (*CancellableTimer) Lock() {}
|
||||
|
||||
// Unlock is a no-op used by the copylocks checker from go vet.
|
||||
//
|
||||
// See CancellableTimer for details about why it shouldn't be copied.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/8005#issuecomment-190753527 for more
|
||||
// details about the copylocks checker.
|
||||
func (*CancellableTimer) Unlock() {}
|
||||
|
||||
// NewCancellableTimer returns an unscheduled CancellableTimer with the given
|
||||
// locker and fn.
|
||||
//
|
||||
// fn MUST NOT attempt to lock locker.
|
||||
//
|
||||
// Callers must call Reset to schedule the timer to fire.
|
||||
func MakeCancellableTimer(locker sync.Locker, fn func()) CancellableTimer {
|
||||
return CancellableTimer{locker: locker, fn: fn}
|
||||
func NewCancellableTimer(locker sync.Locker, fn func()) *CancellableTimer {
|
||||
return &CancellableTimer{locker: locker, fn: fn}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestCancellableTimerReassignment(t *testing.T) {
|
||||
// that has an active timer (even if it has been stopped as a stopped
|
||||
// timer may be blocked on a lock before it can check if it has been
|
||||
// stopped while another goroutine holds the same lock).
|
||||
timer = tcpip.MakeCancellableTimer(&lock, func() {
|
||||
timer = *tcpip.NewCancellableTimer(&lock, func() {
|
||||
wg.Done()
|
||||
})
|
||||
timer.Reset(shortDuration)
|
||||
@@ -59,7 +59,7 @@ func TestCancellableTimerFire(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
var lock sync.Mutex
|
||||
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() {
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() {
|
||||
ch <- struct{}{}
|
||||
})
|
||||
timer.Reset(shortDuration)
|
||||
@@ -85,7 +85,7 @@ func TestCancellableTimerResetFromLongDuration(t *testing.T) {
|
||||
ch := make(chan struct{})
|
||||
var lock sync.Mutex
|
||||
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer.Reset(middleDuration)
|
||||
|
||||
lock.Lock()
|
||||
@@ -116,7 +116,7 @@ func TestCancellableTimerResetFromShortDuration(t *testing.T) {
|
||||
var lock sync.Mutex
|
||||
|
||||
lock.Lock()
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer.Reset(shortDuration)
|
||||
timer.StopLocked()
|
||||
lock.Unlock()
|
||||
@@ -153,7 +153,7 @@ func TestCancellableTimerImmediatelyStop(t *testing.T) {
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
lock.Lock()
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer.Reset(shortDuration)
|
||||
timer.StopLocked()
|
||||
lock.Unlock()
|
||||
@@ -174,7 +174,7 @@ func TestCancellableTimerStoppedResetWithoutLock(t *testing.T) {
|
||||
var lock sync.Mutex
|
||||
|
||||
lock.Lock()
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer.Reset(shortDuration)
|
||||
timer.StopLocked()
|
||||
lock.Unlock()
|
||||
@@ -205,7 +205,7 @@ func TestManyCancellableTimerResetAfterBlockedOnLock(t *testing.T) {
|
||||
var lock sync.Mutex
|
||||
|
||||
lock.Lock()
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer.Reset(shortDuration)
|
||||
for i := 0; i < 10; i++ {
|
||||
// Sleep until the timer fires and gets blocked trying to take the lock.
|
||||
@@ -237,7 +237,7 @@ func TestManyCancellableTimerResetUnderLock(t *testing.T) {
|
||||
var lock sync.Mutex
|
||||
|
||||
lock.Lock()
|
||||
timer := tcpip.MakeCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer := tcpip.NewCancellableTimer(&lock, func() { ch <- struct{}{} })
|
||||
timer.Reset(shortDuration)
|
||||
for i := 0; i < 10; i++ {
|
||||
timer.StopLocked()
|
||||
|
||||
Reference in New Issue
Block a user