From 1aa2cd1df614925cf68964239eeaaf42ea74bc43 Mon Sep 17 00:00:00 2001 From: Adam Smith Date: Tue, 29 Sep 2026 19:30:18 +0000 Subject: wwan: T7487: catch malformed mmcli JSON, not just OSError mmcli can return empty or non-JSON output while ModemManager is still starting (T6604), and json.loads() raising on that is a ValueError, not an OSError - it was propagating straight out of _modem_owning_port() uncaught. Under wait=True that reaches wait_for()'s callback and aborts the poll loop instead of retrying, exactly the startup race this module exists to ride out. Co-authored-by: Christian Breunig --- python/vyos/utils/wwan.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'python') diff --git a/python/vyos/utils/wwan.py b/python/vyos/utils/wwan.py index af719571d..8ee6a5a9a 100644 --- a/python/vyos/utils/wwan.py +++ b/python/vyos/utils/wwan.py @@ -59,17 +59,25 @@ def _modem_owning_port(ifname: str): from json import loads try: - modem_list = loads(cmdl(['mmcli', '--list-modems', '--output-json'])).get( - 'modem-list', [] - ) - except OSError: + data = loads(cmdl(['mmcli', '--list-modems', '--output-json'])) + except (OSError, ValueError): + # ValueError also catches json.JSONDecodeError - mmcli can return + # empty or malformed output while ModemManager is still starting + # (T6604), and that must retry under wait=True, not abort it. + return None + + # Well-formed JSON of an unexpected shape is treated like no modems at all + modem_list = [] + if isinstance(data, dict) and 'modem-list' in data: + modem_list = data['modem-list'] + if not isinstance(modem_list, list): return None for modem_path in modem_list: idx = modem_path.rsplit('/', 1)[-1] try: detail = loads(cmdl(['mmcli', '--modem', idx, '--output-json'])) - except OSError: + except (OSError, ValueError): continue ports = dict_search('modem.generic.ports', detail) or [] if any(port.split(' ')[0] == ifname for port in ports): -- cgit v1.2.3