I need to monitor the status of the N sensors and log it. I am creating a
separate goroutine for each sensor which fetches the state and logs it at
regular intervals. For each goroutine, a channel is created to read the
termination signal. Each sensor's state is maintained in sync.Map. The map
maintains a pointer to the state. Apart from monitoring goroutines, there
are processing goroutines that update the sensor's state.
In my current implementation, the goroutines are able to log the status at
regular intervals. But after a few days, some goroutines stop logging the
status. But the processing goroutines are able to update the status.
As a goroutine may terminate if panic occurs, I used recover() to log the
error and the monitoring thread is re-created. But this doesn't help
either. I noticed that the goroutine has been terminated but error hasn't
been logged.
I suspect that because of memory leak, the goroutine might be terminated.
Please find attached sample code.
It will be helpful if someone explains this abnormal behavior and provides
possible solutions.
Thanks
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/0936fbc8-9f47-45ca-9e93-a6f6590f3adcn%40googlegroups.com.
// sensor state struct
type sensorState struct {
a float64
b int
lock sync.Mutex
ch chan int
}
type curStatus struct {
a float64
b int
...
}
// log struct
type stateLog struct {
state curStatus
timestamp int64
method string
}
// stateMap maintains state of different sensors
var stateMap sync.Map
stateMap.Store("Sensor-A", &sensorState{
a : 0,
b : 0,
lock : sync.Mutex{},
ch : make(chan int)
})
func ChargerMonitoringThreadV2(sensorId string) {
isStateLocked := false
sensorStatus := curStatus{}
sessionState, _ := stateMap.Load(sensorId)
state, _ := sessionState.(*sensorState)
defer func() {
if er := recover(); er != nil {
fmt.Printf("ERROR: [sensorId:%s][ChargerMonitoringThreadV2]
Recovered from - %v", sensorId, er)
fmt.Printf("ERROR: [sensorId:%s][ChargerMonitoringThreadV2]
stacktrace from panic:\n%s", sensorId, string(debug.Stack()))
if isStateLocked {
fmt.Printf("INFO: [sensorId:%s][ChargerMonitoringThreadV2]
Released lock\n", sensorId)
state.lock.Unlock()
isStateLocked = false
}
go ChargerMonitoringThreadV2(sensorId)
logging.ReportException(fmt.Errorf("%v\n%s", er,
string(debug.Stack()))) // log error
return
}
}()
for {
select {
case <-state.ch:
fmt.Printf("INFO: [sensorId:%s][monitoringThread] Terminating
monitoring thread...\n", sensorId)
return
default:
curTS := time.Now().UnixMilli()
state.lock.Lock()
isSessionStateLocked = true
sensorStatus.a = state.a
state.lock.Unlock()
isSessionStateLocked = false
insertLog(&stateLog{
state: sensorStatus,
timestamp: curTS,
method: "monitoringThread",
})
time.Sleep(60 * time.Second)
}
}
}