@ -58,6 +58,7 @@ type winMon struct {
pollTicker * time . Ticker
pollTicker * time . Ticker
lastState * interfaces . State
lastState * interfaces . State
closeHandle windows . Handle // signaled upon close
closeHandle windows . Handle // signaled upon close
goroutineDoneCh chan struct { } // closed when awaitIPAndRouteChanges goroutine has stopped
mu sync . Mutex
mu sync . Mutex
lastNetChange time . Time
lastNetChange time . Time
@ -78,6 +79,7 @@ func newOSMon(logf logger.Logf) (osMon, error) {
messagec : make ( chan messageOrError , 1 ) ,
messagec : make ( chan messageOrError , 1 ) ,
pollTicker : time . NewTicker ( pollIntervalSlow ) ,
pollTicker : time . NewTicker ( pollIntervalSlow ) ,
closeHandle : closeHandle ,
closeHandle : closeHandle ,
goroutineDoneCh : make ( chan struct { } ) ,
}
}
go m . awaitIPAndRouteChanges ( )
go m . awaitIPAndRouteChanges ( )
return m , nil
return m , nil
@ -87,6 +89,12 @@ func (m *winMon) Close() error {
m . cancel ( )
m . cancel ( )
m . pollTicker . Stop ( )
m . pollTicker . Stop ( )
windows . SetEvent ( m . closeHandle ) // wakes up any reader blocked in Receive
windows . SetEvent ( m . closeHandle ) // wakes up any reader blocked in Receive
// Wait for awaitIPAndRouteChannges to be done, which could
// still be using the m.closeHandle.
<- m . goroutineDoneCh
windows . CloseHandle ( m . closeHandle )
return nil
return nil
}
}
@ -125,6 +133,7 @@ func (m *winMon) stateChanged() bool {
}
}
func ( m * winMon ) awaitIPAndRouteChanges ( ) {
func ( m * winMon ) awaitIPAndRouteChanges ( ) {
defer close ( m . goroutineDoneCh )
for {
for {
msg , err := m . getIPOrRouteChangeMessage ( )
msg , err := m . getIPOrRouteChangeMessage ( )
if err == errClosed {
if err == errClosed {