summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-01-28 16:59:45 +0100
committerThomas Haller <thaller@redhat.com>2022-02-02 11:08:30 +0100
commitf00980e5cae536d35e39e28e2b796de1d7f27f4c (patch)
tree9cc53a5fa684933058e4675746489cd9b45a90dc
parent601285301041e3f59eb74473f29d1847c3a2ec82 (diff)
l3cfg: add assertion for scheduling timeout in _l3_acd_data_timeout_schedule()
The first point is that ACD timeout is strongly tied to the current state. That is (somewhat) obvious, because _l3_acd_data_state_set_full() will clear any pending timeout. So you can only schedule a timeout *after* setting the state, and setting the next state, will clear the timeout. Likewise, note that l3_acd_data_state_change() for the event ACD_STATE_CHANGE_MODE_TIMEOUT asserts that it is only called in the few states where that is expected. See rhbz#2047788 where that assertion gets hit. The first point means that we must only schedule a timer when we are also in a state that supports that. Add an assertion for that at the point when scheduling the timeout. The assert at this point is useful, because it catches the moment when we do the wrong thing (instead of getting the assertion later during the timeout, when we no longer know where the error happened). See-also: https://bugzilla.redhat.com/show_bug.cgi?id=2047788
-rw-r--r--src/core/nm-l3cfg.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
index 48a491193b..fc3b427894 100644
--- a/src/core/nm-l3cfg.c
+++ b/src/core/nm-l3cfg.c
@@ -1929,6 +1929,19 @@ _l3_acd_data_timeout_cb(gpointer user_data)
static void
_l3_acd_data_timeout_schedule(AcdData *acd_data, gint64 timeout_msec)
{
+ /* in _l3_acd_data_state_set_full() we clear the timer. At the same time,
+ * in _l3_acd_data_state_change(ACD_STATE_CHANGE_MODE_TIMEOUT) we only
+ * expect timeouts in certain states.
+ *
+ * That means, scheduling a timeout is only correct if we are in a certain
+ * state, which allows to handle timeouts. This assert checks for that to
+ * ensure we don't call a timeout in an unexpected state. */
+ nm_assert(NM_IN_SET(acd_data->info.state,
+ NM_L3_ACD_ADDR_STATE_PROBING,
+ NM_L3_ACD_ADDR_STATE_USED,
+ NM_L3_ACD_ADDR_STATE_DEFENDING,
+ NM_L3_ACD_ADDR_STATE_CONFLICT));
+
nm_clear_g_source_inst(&acd_data->acd_data_timeout_source);
acd_data->acd_data_timeout_source =
nm_g_timeout_add_source(NM_CLAMP((gint64) 0, timeout_msec, (gint64) G_MAXUINT),