From f29a6bfa17c9e31a4e2f392821ebd33a89c03f0c Mon Sep 17 00:00:00 2001 From: Goffi Date: Wed, 8 Sep 2021 11:16:21 +0200 Subject: [PATCH] bridge (dbus/frontend): reintrospect signature in case of guess error: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a "Unable to guess signature […]" `ValueError` is raised during a method call, the signatures are re-introspected. This should fix this issue when a frontend is launched just after to the backend (this happens notably with tests). --- .../dbus/dbus_frontend_template.py | 49 ++++++++++++++++--- sat_frontends/bridge/dbus_bridge.py | 49 ++++++++++++++++--- 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py b/sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py index a8addfd1..877f00bc 100644 --- a/sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py +++ b/sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py @@ -140,7 +140,21 @@ class Bridge: kwargs['reply_handler'] = _callback kwargs['error_handler'] = lambda err: _errback(dbus_to_bridge_exception(err)) - return method(*args, **kwargs) + try: + return method(*args, **kwargs) + except ValueError as e: + if e.args[0].startswith("Unable to guess signature"): + # XXX: if frontend is started too soon after backend, the + # inspection misses methods (notably plugin dynamically added + # methods). The following hack works around that by redoing the + # cache of introspected methods signatures. + log.debug("using hack to work around inspection issue") + proxy = self.db_plugin_iface.proxy_object + IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS + proxy._introspect_state = IN_PROGRESS + proxy._Introspect() + return self.db_plugin_iface.get_dbus_method(name)(*args, **kwargs) + raise e return getPluginMethod @@ -167,13 +181,32 @@ class AIOBridge(Bridge): fut.set_result, ret) error_handler = lambda err: loop.call_soon_threadsafe( fut.set_exception, dbus_to_bridge_exception(err)) - method( - *args, - **kwargs, - timeout=const_TIMEOUT, - reply_handler=reply_handler, - error_handler=error_handler - ) + try: + method( + *args, + **kwargs, + timeout=const_TIMEOUT, + reply_handler=reply_handler, + error_handler=error_handler + ) + except ValueError as e: + if e.args[0].startswith("Unable to guess signature"): + # same hack as for Bridge.__getattribute__ + log.warning("using hack to work around inspection issue") + proxy = self.db_plugin_iface.proxy_object + IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS + proxy._introspect_state = IN_PROGRESS + proxy._Introspect() + self.db_plugin_iface.get_dbus_method(name)( + *args, + **kwargs, + timeout=const_TIMEOUT, + reply_handler=reply_handler, + error_handler=error_handler + ) + + else: + raise e return fut return getPluginMethod diff --git a/sat_frontends/bridge/dbus_bridge.py b/sat_frontends/bridge/dbus_bridge.py index b250607d..14926b1f 100644 --- a/sat_frontends/bridge/dbus_bridge.py +++ b/sat_frontends/bridge/dbus_bridge.py @@ -140,7 +140,21 @@ class Bridge: kwargs['reply_handler'] = _callback kwargs['error_handler'] = lambda err: _errback(dbus_to_bridge_exception(err)) - return method(*args, **kwargs) + try: + return method(*args, **kwargs) + except ValueError as e: + if e.args[0].startswith("Unable to guess signature"): + # XXX: if frontend is started too soon after backend, the + # inspection misses methods (notably plugin dynamically added + # methods). The following hack works around that by redoing the + # cache of introspected methods signatures. + log.debug("using hack to work around inspection issue") + proxy = self.db_plugin_iface.proxy_object + IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS + proxy._introspect_state = IN_PROGRESS + proxy._Introspect() + return self.db_plugin_iface.get_dbus_method(name)(*args, **kwargs) + raise e return getPluginMethod @@ -930,13 +944,32 @@ class AIOBridge(Bridge): fut.set_result, ret) error_handler = lambda err: loop.call_soon_threadsafe( fut.set_exception, dbus_to_bridge_exception(err)) - method( - *args, - **kwargs, - timeout=const_TIMEOUT, - reply_handler=reply_handler, - error_handler=error_handler - ) + try: + method( + *args, + **kwargs, + timeout=const_TIMEOUT, + reply_handler=reply_handler, + error_handler=error_handler + ) + except ValueError as e: + if e.args[0].startswith("Unable to guess signature"): + # same hack as for Bridge.__getattribute__ + log.warning("using hack to work around inspection issue") + proxy = self.db_plugin_iface.proxy_object + IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS + proxy._introspect_state = IN_PROGRESS + proxy._Introspect() + self.db_plugin_iface.get_dbus_method(name)( + *args, + **kwargs, + timeout=const_TIMEOUT, + reply_handler=reply_handler, + error_handler=error_handler + ) + + else: + raise e return fut return getPluginMethod