accounting: bwlimit signal handler should always start

The SIGUSR2 signal handler for bandwidth limits currently only starts
if rclone is started at a time when a bandwidth limit applies. This
means that if rclone starts _outside_ such a time, i.e. with no
bandwidth limits, then enters a time where bandwidth limits do apply,
it will not be possible to use SIGUSR2 to toggle it.

This fixes that by always starting the signal handler, but only
toggling the limiter if there is a bandwidth limit configured.
This commit is contained in:
Sam Lai 2023-06-22 17:59:24 +01:00 committed by GitHub
parent da955e5d4f
commit b26db8e640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 24 deletions

View File

@ -23,15 +23,26 @@ func (tb *tokenBucket) startSignalHandler() {
// This runs forever, but blocks until the signal is received.
for {
<-signals
tb.mu.Lock()
tb.toggledOff = !tb.toggledOff
tb.curr, tb.prev = tb.prev, tb.curr
s := "disabled"
if !tb.curr._isOff() {
s = "enabled"
}
tb.mu.Unlock()
fs.Logf(nil, "Bandwidth limit %s by user", s)
func() {
tb.mu.Lock()
defer tb.mu.Unlock()
// if there's no bandwidth limit configured now, do nothing
if !tb.currLimit.Bandwidth.IsSet() {
fs.Debugf(nil, "SIGUSR2 received but no bandwidth limit configured right now, ignoring")
return
}
tb.toggledOff = !tb.toggledOff
tb.curr, tb.prev = tb.prev, tb.curr
s := "disabled"
if !tb.curr._isOff() {
s = "enabled"
}
fs.Logf(nil, "Bandwidth limit %s by user", s)
}()
}
}()
}

View File

@ -30,12 +30,11 @@ type buckets [TokenBucketSlots]*rate.Limiter
// tokenBucket holds info about the rate limiters in use
type tokenBucket struct {
mu sync.RWMutex // protects the token bucket variables
curr buckets
prev buckets
toggledOff bool
currLimitMu sync.Mutex // protects changes to the timeslot
currLimit fs.BwTimeSlot
mu sync.RWMutex // protects the token bucket variables
curr buckets
prev buckets
toggledOff bool
currLimit fs.BwTimeSlot
}
// Return true if limit is disabled
@ -106,11 +105,11 @@ func (tb *tokenBucket) StartTokenBucket(ctx context.Context) {
if tb.currLimit.Bandwidth.IsSet() {
tb.curr = newTokenBucket(tb.currLimit.Bandwidth)
fs.Infof(nil, "Starting bandwidth limiter at %v Byte/s", &tb.currLimit.Bandwidth)
// Start the SIGUSR2 signal handler to toggle bandwidth.
// This function does nothing in windows systems.
tb.startSignalHandler()
}
// Start the SIGUSR2 signal handler to toggle bandwidth.
// This function does nothing in windows systems.
tb.startSignalHandler()
}
// StartTokenTicker creates a ticker to update the bandwidth limiter every minute.
@ -126,11 +125,9 @@ func (tb *tokenBucket) StartTokenTicker(ctx context.Context) {
go func() {
for range ticker.C {
limitNow := ci.BwLimit.LimitAt(time.Now())
tb.currLimitMu.Lock()
tb.mu.Lock()
if tb.currLimit.Bandwidth != limitNow.Bandwidth {
tb.mu.Lock()
// If bwlimit is toggled off, the change should only
// become active on the next toggle, which causes
// an exchange of tb.curr <-> tb.prev
@ -156,9 +153,9 @@ func (tb *tokenBucket) StartTokenTicker(ctx context.Context) {
}
tb.currLimit = limitNow
tb.mu.Unlock()
}
tb.currLimitMu.Unlock()
tb.mu.Unlock()
}
}()
}