This repository has been archived by the owner on May 17, 2024. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
logwriter: resolve deadlock on suppress_lock
There's a strict ordering requirement between suppress_lock and interacting with the main loop. The reason is that the main thread (running the main loop) sometimes acquires suppress_lock (at suppress timer expiration) and while blocking on suppress_lock it cannot service main_loop_calls() This patch makes it sure that ml_batched_timer_update/cancel calls are only done with the suppress lock released. If we do this, we might have a few unfortunate side effects due to races that this patch also tries to handle: Two messages race, one of these matches the recorded last message, the other doesn't. In this case, moving the update on the suppress_timer outside of the lock region might cause two different races: 1) matching message comes first, then non-matching This case the suppress_lock protected region decides that the suppress timer needs to fire (#1) and then the other decides that it needs to be cancelled. (#2) If these are processed in order, then we are the same as if the two was also protected by the mutex (which is ok) If they are reversed, e.g. we first cancels the timer and the second arms it, then we might have a timer wakeup which will find no suppressed messages to report (as the non-matching message will set last_msg_count to zero). This spurious wakeup should be handled by the expiration callback. 1) non-matching message comes first, then matching This is simply a message reordering case, e.g. we don't want any suppressions to be emitted. In this case the locked regions finds that neither messages matched the recorded one, thus both times they decide to cancel the timer, which is ok. Timer cancellation can be reordered as they will have the same effect anyway. Signed-off-by: Balazs Scheidler <balazs.scheidler@balabit.com>
- Loading branch information