changeset 3648:71cfe9334f73

bridge (dbus/frontend): reintrospect signature in case of guess error: 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).
author Goffi <goffi@goffi.org>
date Wed, 08 Sep 2021 11:16:21 +0200
parents 57d43e3e0095
children 4a89342476e9
files sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py sat_frontends/bridge/dbus_bridge.py
diffstat 2 files changed, 82 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py	Wed Sep 08 11:16:00 2021 +0200
+++ b/sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py	Wed Sep 08 11:16:21 2021 +0200
@@ -140,7 +140,21 @@
                     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 @@
                     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
--- a/sat_frontends/bridge/dbus_bridge.py	Wed Sep 08 11:16:00 2021 +0200
+++ b/sat_frontends/bridge/dbus_bridge.py	Wed Sep 08 11:16:21 2021 +0200
@@ -140,7 +140,21 @@
                     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 @@
                     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