@ -14,6 +14,7 @@ import (
"sync"
"sync"
"time"
"time"
"golang.org/x/exp/slices"
"tailscale.com/envknob"
"tailscale.com/envknob"
)
)
@ -84,14 +85,20 @@ func NewPoller() (*Poller, error) {
// Do one initial poll synchronously so we can return an error
// Do one initial poll synchronously so we can return an error
// early.
// early.
var err error
if pl , err := p . getList ( ) ; err != nil {
p . prev , err = p . getList ( )
if err != nil {
return nil , err
return nil , err
} else {
p . setPrev ( pl )
}
}
return p , nil
return p , nil
}
}
func ( p * Poller ) setPrev ( pl List ) {
// Make a copy, as the pass in pl slice aliases pl.scratch and we don't want
// that to except to the caller.
p . prev = slices . Clone ( pl )
}
func ( p * Poller ) initOSField ( ) {
func ( p * Poller ) initOSField ( ) {
if newOSImpl != nil {
if newOSImpl != nil {
p . os = newOSImpl ( )
p . os = newOSImpl ( )
@ -131,11 +138,14 @@ func (p *Poller) send(ctx context.Context, pl List) (sent bool, err error) {
//
//
// Run may only be called once.
// Run may only be called once.
func ( p * Poller ) Run ( ctx context . Context ) error {
func ( p * Poller ) Run ( ctx context . Context ) error {
defer close ( p . runDone )
defer close ( p . c )
tick := time . NewTicker ( pollInterval )
tick := time . NewTicker ( pollInterval )
defer tick . Stop ( )
defer tick . Stop ( )
return p . runWithTickChan ( ctx , tick . C )
}
func ( p * Poller ) runWithTickChan ( ctx context . Context , tickChan <- chan time . Time ) error {
defer close ( p . runDone )
defer close ( p . c )
// Send out the pre-generated initial value.
// Send out the pre-generated initial value.
if sent , err := p . send ( ctx , p . prev ) ; ! sent {
if sent , err := p . send ( ctx , p . prev ) ; ! sent {
@ -144,7 +154,7 @@ func (p *Poller) Run(ctx context.Context) error {
for {
for {
select {
select {
case <- tick . C:
case <- tick Chan :
pl , err := p . getList ( )
pl , err := p . getList ( )
if err != nil {
if err != nil {
return err
return err
@ -152,9 +162,7 @@ func (p *Poller) Run(ctx context.Context) error {
if pl . equal ( p . prev ) {
if pl . equal ( p . prev ) {
continue
continue
}
}
// New value. Make a copy, as pl might alias pl.scratch
p . setPrev ( pl )
// and prev must not.
p . prev = append ( [ ] Port ( nil ) , pl ... )
if sent , err := p . send ( ctx , p . prev ) ; ! sent {
if sent , err := p . send ( ctx , p . prev ) ; ! sent {
return err
return err
}
}