diff options
author | Thomas Haller <thaller@redhat.com> | 2022-01-28 16:59:45 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-02-02 11:08:30 +0100 |
commit | f00980e5cae536d35e39e28e2b796de1d7f27f4c (patch) | |
tree | 9cc53a5fa684933058e4675746489cd9b45a90dc | |
parent | 601285301041e3f59eb74473f29d1847c3a2ec82 (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.c | 13 |
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), |