mirror of
https://github.com/rclone/rclone
synced 2024-11-24 01:26:25 +01:00
oauthutil: add Shutdown method
Before this change, calling the `oauthutil.NewRenew` func may cause goroutine leaks. This change adds a `Shutdown` method to allow the caller to exit the goroutine to avoid leaks. Signed-off-by: rkonfj <rkonfj@gmail.com>
This commit is contained in:
parent
110d07548f
commit
6c58e9976c
@ -1,6 +1,7 @@
|
||||
package oauthutil
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/rclone/rclone/fs"
|
||||
@ -8,10 +9,12 @@ import (
|
||||
|
||||
// Renew allows tokens to be renewed on expiry if uploads are in progress.
|
||||
type Renew struct {
|
||||
name string // name to use in logs
|
||||
ts *TokenSource // token source that needs renewing
|
||||
uploads atomic.Int32 // number of uploads in progress
|
||||
run func() error // a transaction to run to renew the token on
|
||||
name string // name to use in logs
|
||||
ts *TokenSource // token source that needs renewing
|
||||
uploads atomic.Int32 // number of uploads in progress
|
||||
run func() error // a transaction to run to renew the token on
|
||||
done chan any // channel to end the go routine
|
||||
shutdown sync.Once
|
||||
}
|
||||
|
||||
// NewRenew creates a new Renew struct and starts a background process
|
||||
@ -24,6 +27,7 @@ func NewRenew(name string, ts *TokenSource, run func() error) *Renew {
|
||||
name: name,
|
||||
ts: ts,
|
||||
run: run,
|
||||
done: make(chan any),
|
||||
}
|
||||
go r.renewOnExpiry()
|
||||
return r
|
||||
@ -36,7 +40,11 @@ func NewRenew(name string, ts *TokenSource, run func() error) *Renew {
|
||||
func (r *Renew) renewOnExpiry() {
|
||||
expiry := r.ts.OnExpiry()
|
||||
for {
|
||||
<-expiry
|
||||
select {
|
||||
case <-expiry:
|
||||
case <-r.done:
|
||||
return
|
||||
}
|
||||
uploads := r.uploads.Load()
|
||||
if uploads != 0 {
|
||||
fs.Debugf(r.name, "Token expired - %d uploads in progress - refreshing", uploads)
|
||||
@ -72,3 +80,15 @@ func (r *Renew) Invalidate() {
|
||||
func (r *Renew) Expire() error {
|
||||
return r.ts.Expire()
|
||||
}
|
||||
|
||||
// Shutdown stops the timer and no more renewal will take place.
|
||||
func (r *Renew) Shutdown() {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
// closing a channel can only be done once
|
||||
r.shutdown.Do(func() {
|
||||
r.ts.expiryTimer.Stop()
|
||||
close(r.done)
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user