mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 20:09:41 +01:00
Possible IdleTimer lock fix
This commit is contained in:
parent
cabb3b219d
commit
7b88d21e58
@ -37,29 +37,42 @@ type IdleTimer struct {
|
|||||||
sync.Mutex // tier 1
|
sync.Mutex // tier 1
|
||||||
|
|
||||||
// immutable after construction
|
// immutable after construction
|
||||||
registerTimeout time.Duration
|
registerTimeout time.Duration
|
||||||
idleTimeout time.Duration
|
quitTimeout time.Duration
|
||||||
idleTimeoutWithResume time.Duration
|
client *Client
|
||||||
quitTimeout time.Duration
|
|
||||||
client *Client
|
|
||||||
|
|
||||||
// mutable
|
// mutable
|
||||||
state TimerState
|
idleTimeout time.Duration
|
||||||
timer *time.Timer
|
state TimerState
|
||||||
|
timer *time.Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIdleTimer sets up a new IdleTimer using constant timeouts.
|
// NewIdleTimer sets up a new IdleTimer using constant timeouts.
|
||||||
func NewIdleTimer(client *Client) *IdleTimer {
|
func NewIdleTimer(client *Client) *IdleTimer {
|
||||||
it := IdleTimer{
|
it := IdleTimer{
|
||||||
registerTimeout: RegisterTimeout,
|
registerTimeout: RegisterTimeout,
|
||||||
idleTimeout: IdleTimeout,
|
idleTimeout: IdleTimeout,
|
||||||
idleTimeoutWithResume: IdleTimeoutWithResumeCap,
|
quitTimeout: QuitTimeout,
|
||||||
quitTimeout: QuitTimeout,
|
client: client,
|
||||||
client: client,
|
|
||||||
}
|
}
|
||||||
return &it
|
return &it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateIdleDuration updates the idle duration, given the client's caps.
|
||||||
|
func (it *IdleTimer) updateIdleDuration() {
|
||||||
|
newIdleTime := IdleTimeout
|
||||||
|
|
||||||
|
// if they have the resume cap, wait longer before pinging them out
|
||||||
|
// to give them a chance to resume their connection
|
||||||
|
if it.client.capabilities.Has(caps.Resume) {
|
||||||
|
newIdleTime = IdleTimeoutWithResumeCap
|
||||||
|
}
|
||||||
|
|
||||||
|
it.Lock()
|
||||||
|
defer it.Unlock()
|
||||||
|
it.idleTimeout = newIdleTime
|
||||||
|
}
|
||||||
|
|
||||||
// Start starts counting idle time; if there is no activity from the client,
|
// Start starts counting idle time; if there is no activity from the client,
|
||||||
// it will eventually be stopped.
|
// it will eventually be stopped.
|
||||||
func (it *IdleTimer) Start() {
|
func (it *IdleTimer) Start() {
|
||||||
@ -75,6 +88,8 @@ func (it *IdleTimer) Touch() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it.updateIdleDuration()
|
||||||
|
|
||||||
it.Lock()
|
it.Lock()
|
||||||
defer it.Unlock()
|
defer it.Unlock()
|
||||||
// a touch transitions TimerUnregistered or TimerIdle into TimerActive
|
// a touch transitions TimerUnregistered or TimerIdle into TimerActive
|
||||||
@ -85,6 +100,8 @@ func (it *IdleTimer) Touch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (it *IdleTimer) processTimeout() {
|
func (it *IdleTimer) processTimeout() {
|
||||||
|
it.updateIdleDuration()
|
||||||
|
|
||||||
var previousState TimerState
|
var previousState TimerState
|
||||||
func() {
|
func() {
|
||||||
it.Lock()
|
it.Lock()
|
||||||
@ -125,13 +142,7 @@ func (it *IdleTimer) resetTimeout() {
|
|||||||
case TimerUnregistered:
|
case TimerUnregistered:
|
||||||
nextTimeout = it.registerTimeout
|
nextTimeout = it.registerTimeout
|
||||||
case TimerActive:
|
case TimerActive:
|
||||||
// if they have the resume cap, wait longer before pinging them out
|
nextTimeout = it.idleTimeout
|
||||||
// to give them a chance to resume their connection
|
|
||||||
if it.client.capabilities.Has(caps.Resume) {
|
|
||||||
nextTimeout = it.idleTimeoutWithResume
|
|
||||||
} else {
|
|
||||||
nextTimeout = it.idleTimeout
|
|
||||||
}
|
|
||||||
case TimerIdle:
|
case TimerIdle:
|
||||||
nextTimeout = it.quitTimeout
|
nextTimeout = it.quitTimeout
|
||||||
case TimerDead:
|
case TimerDead:
|
||||||
@ -146,6 +157,8 @@ func (it *IdleTimer) quitMessage(state TimerState) string {
|
|||||||
return fmt.Sprintf("Registration timeout: %v", it.registerTimeout)
|
return fmt.Sprintf("Registration timeout: %v", it.registerTimeout)
|
||||||
case TimerIdle:
|
case TimerIdle:
|
||||||
// how many seconds before registered clients are timed out (IdleTimeout plus QuitTimeout).
|
// how many seconds before registered clients are timed out (IdleTimeout plus QuitTimeout).
|
||||||
|
it.Lock()
|
||||||
|
defer it.Unlock()
|
||||||
return fmt.Sprintf("Ping timeout: %v", (it.idleTimeout + it.quitTimeout))
|
return fmt.Sprintf("Ping timeout: %v", (it.idleTimeout + it.quitTimeout))
|
||||||
default:
|
default:
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
|
Loading…
Reference in New Issue
Block a user