You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Prevent the router from deadlocking itself when calling Commit()
Backport of #13717
The router reload function (Commit()) was changed so that it could be
rate limited. The rate limiter tracks changes in a kcache.Queue
object. It will coalesce changes to the same call so that if three
calls to Invoke() the rate limited function happen before the next
time it is allowed to process, then only one will occur.
Our problem was that we were doing:
Thread 1 (the rate-limiter background process):
- Wake up
- Ratelimit sees there is work to be done and calls fifo.go's Pop() function
- Fifo.go acquires a fifo lock and call the processing function
- Router.go's commitAndReload() function acquires a lock on the router object
Thread 2 (triggered by the event handler that commit's changes to the router):
- Get the event and process it
- Since there are changes to be made, call router.Commit()
- Commit() grabs a lock on the router object
- Then calls the rate-limiter wrapper around commitAndReload() using Invoke() to queue work
- In order to queue the work... it acquires a lock on the fifo
So thread 1 locks: fifo then router; thread 2 locks: router then fifo.
If you get unlucky, those threads deadlock and you never process
another event.
The fix is to release the lock on the router object in our Commit()
function before we call Invoke on the rate limited function. The lock
is not actually protecting anything at that point since the rate
limited function does its own locking, and is run in a separate thread
anyway.
Bug 1440977 (https://bugzilla.redhat.com/show_bug.cgi?id=1440977)
0 commit comments