mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 00:20:11 +01:00
acd: fix crash in acd-event loop
Don't emit signals while popping acd events. Otherwise, we can get
a crash:
#0 0x000055c2bb094e3b in n_acd_pop_event (acd=0x0, eventp=eventp@entry=0x7ffd47de65b0) at shared/n-acd/src/n-acd.c:846
node = <optimized out>
t_node = <optimized out>
#1 0x000055c2baff53be in acd_event (source=<optimized out>, condition=<optimized out>, data=0x55c2bc4a6cf0) at src/devices/nm-acd-manager.c:180
self = 0x55c2bc4a6cf0
priv = 0x55c2bc4a6d08
__func__ = "acd_event"
event = 0x55c2bc593af0
info = 0x55c2bc4b76c0
address_str = "\000\000\000\000\000\000\000\000\bd\373\272\302U\000"
hwaddr_str = 0x0
r = <optimized out>
#2 0x00007eff336238f9 in g_main_context_dispatch (context=0x55c2bc41f480) at gmain.c:3146
dispatch = 0x7eff336688a0 <g_io_unix_dispatch>
prev_source = 0x0
was_in_call = 0
user_data = 0x55c2bc4a6cf0
callback = 0x55c2baff5310 <acd_event>
cb_funcs = 0x7eff338eb920 <g_source_callback_funcs>
cb_data = 0x55c2bc558680
need_destroy = <optimized out>
source = 0x55c2bc58c160
current = 0x55c2bc43dd10
i = 0
...
While at it, don't return from the events N_ACD_EVENT_DEFENDED,
N_ACD_EVENT_CONFLICT, and <default>, but continue popping events.
Fixes: d9a4b59c18
This commit is contained in:
parent
793afb7d95
commit
29c95cd98a
1 changed files with 16 additions and 6 deletions
|
|
@ -170,6 +170,7 @@ acd_event (GIOChannel *source, GIOCondition condition, gpointer data)
|
|||
NMAcdManagerPrivate *priv = NM_ACD_MANAGER_GET_PRIVATE (self);
|
||||
NAcdEvent *event;
|
||||
AddressInfo *info;
|
||||
gboolean emit_probe_terminated = FALSE;
|
||||
char address_str[INET_ADDRSTRLEN];
|
||||
gs_free char *hwaddr_str = NULL;
|
||||
int r;
|
||||
|
|
@ -177,7 +178,10 @@ acd_event (GIOChannel *source, GIOCondition condition, gpointer data)
|
|||
if (n_acd_dispatch (priv->acd))
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
while (!n_acd_pop_event (priv->acd, &event) && event) {
|
||||
while ( !n_acd_pop_event (priv->acd, &event)
|
||||
&& event) {
|
||||
gboolean check_probing_done = FALSE;
|
||||
|
||||
switch (event->event) {
|
||||
case N_ACD_EVENT_READY:
|
||||
n_acd_probe_get_userdata (event->ready.probe, (void **) &info);
|
||||
|
|
@ -195,10 +199,12 @@ acd_event (GIOChannel *source, GIOCondition condition, gpointer data)
|
|||
nm_utils_inet4_ntop (info->address, address_str));
|
||||
}
|
||||
}
|
||||
check_probing_done = TRUE;
|
||||
break;
|
||||
case N_ACD_EVENT_USED:
|
||||
n_acd_probe_get_userdata (event->used.probe, (void **) &info);
|
||||
info->duplicate = TRUE;
|
||||
check_probing_done = TRUE;
|
||||
break;
|
||||
case N_ACD_EVENT_DEFENDED:
|
||||
n_acd_probe_get_userdata (event->defended.probe, (void **) &info);
|
||||
|
|
@ -206,7 +212,7 @@ acd_event (GIOChannel *source, GIOCondition condition, gpointer data)
|
|||
nm_utils_inet4_ntop (info->address, address_str),
|
||||
(hwaddr_str = nm_utils_hwaddr_ntoa (event->defended.sender,
|
||||
event->defended.n_sender)));
|
||||
return G_SOURCE_CONTINUE;
|
||||
break;
|
||||
case N_ACD_EVENT_CONFLICT:
|
||||
n_acd_probe_get_userdata (event->conflict.probe, (void **) &info);
|
||||
_LOGW ("conflict for address %s detected with host %s on interface '%s'",
|
||||
|
|
@ -214,19 +220,23 @@ acd_event (GIOChannel *source, GIOCondition condition, gpointer data)
|
|||
(hwaddr_str = nm_utils_hwaddr_ntoa (event->defended.sender,
|
||||
event->defended.n_sender)),
|
||||
nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex));
|
||||
return G_SOURCE_CONTINUE;
|
||||
break;
|
||||
default:
|
||||
_LOGD ("unhandled event '%s'", acd_event_to_string (event->event));
|
||||
return G_SOURCE_CONTINUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( priv->state == STATE_PROBING
|
||||
if ( check_probing_done
|
||||
&& priv->state == STATE_PROBING
|
||||
&& ++priv->completed == g_hash_table_size (priv->addresses)) {
|
||||
priv->state = STATE_PROBE_DONE;
|
||||
g_signal_emit (self, signals[PROBE_TERMINATED], 0);
|
||||
emit_probe_terminated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (emit_probe_terminated)
|
||||
g_signal_emit (self, signals[PROBE_TERMINATED], 0);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue