Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: no more introspection after "Improve unmarshall performance" #142

Open
whot opened this issue Nov 17, 2022 · 0 comments · May be fixed by #143
Open

Regression: no more introspection after "Improve unmarshall performance" #142

whot opened this issue Nov 17, 2022 · 0 comments · May be fixed by #143

Comments

@whot
Copy link
Contributor

whot commented Nov 17, 2022

Commit "Improve unmarshall performance" (3282eed) broke the introspection abilities. Trying to introspect now simply gives Remote peer disconnected.

Can be reproduced with the example high level service from the docs or this GLib based one:

#!/usr/bin/env python3
from dbus_next import BusType, Variant, PropertyAccess, DBusError
from dbus_next.glib import MessageBus
from dbus_next.service import ServiceInterface, method, dbus_property, signal
from gi.repository import GLib

import dbus_next


class Foo(ServiceInterface):
    def __init_(self, bus):
        bus.export("/com/example/sample0")

    @dbus_property(access=PropertyAccess.READ)
    def Integer(self) -> "i":  # type: ignore
        return 1


bus = MessageBus(bus_type=BusType.SESSION).connect_sync()
bus.request_name_sync("com.example.name", dbus_next.NameFlag.REPLACE_EXISTING)

try:
    mainloop = GLib.MainLoop()
    mainloop.run()
except KeyboardInterrupt:
    pass

To trigger the error, run this command:

$ gdbus introspect --session --dest com.example.name --object-path /com/example/sample0
Error: GDBus.Error:org.freedesktop.DBus.Error.NoReply: Remote peer disconnected

In the GLib case it fails quietly with no error, the asyncio case returns this traceback:

/home/whot/tmp/2022-11-17-Thu/test_async.py:65: DeprecationWarning: There is no current event loop
  asyncio.get_event_loop().run_until_complete(main())
Traceback (most recent call last):
  File "/home/whot/tmp/2022-11-17-Thu/test_async.py", line 65, in <module>
    asyncio.get_event_loop().run_until_complete(main())
  File "/usr/lib64/python3.11/asyncio/base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/whot/tmp/2022-11-17-Thu/test_async.py", line 63, in main
    await bus.wait_for_disconnect()
  File "/home/whot/.local/lib/python3.11/site-packages/dbus_next/aio/message_bus.py", line 342, in wait_for_disconnect
    return await self._disconnect_future
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/whot/.local/lib/python3.11/site-packages/dbus_next/aio/message_bus.py", line 365, in _message_reader
    if self._unmarshaller.unmarshall():
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/whot/.local/lib/python3.11/site-packages/dbus_next/_private/unmarshaller.py", line 297, in unmarshall
    self._read_header()
  File "/home/whot/.local/lib/python3.11/site-packages/dbus_next/_private/unmarshaller.py", line 247, in _read_header
    self.flag = MESSAGE_FLAG_MAP[buffer[2]]
                ~~~~~~~~~~~~~~~~^^^^^^^^^^^
KeyError: 0
whot added a commit to whot/python-dbus-next that referenced this issue Nov 17, 2022
Rather than creating a map of {value: enum}, let's just use Foo(value)
to resolve to the respective enum value.

This fixes a regression with introspection introduced in
commit 3282eed "Improve unmarshall performance":

  File "dbus_next/_private/unmarshaller.py", line 247, in _read_header
    self.flag = MESSAGE_FLAG_MAP[buffer[2]]
                ~~~~~~~~~~~~~~~~^^^^^^^^^^^
  KeyError: 0

MESSAGE_FLAG_MAP is built like this:
    MESSAGE_FLAG_MAP = {field.value: field for field in MessageFlag}

But MessageFlag is a IntFlag, so the zero value (NONE) is missing from
the iterator:

  >>> [f for f in dbus_next.constants.MessageFlag]
  [<MessageFlag.NO_REPLY_EXPECTED: 1>, <MessageFlag.NO_AUTOSTART: 2>,
   <MessageFlag.ALLOW_INTERACTIVE_AUTHORIZATION: 4>]

Resolving the enum through the constructor fixes this. MESSAGE_TYPE_MAP
and HEADER_NAME_MAP are changed in solidarity.

Fixes altdesktop#142
@whot whot linked a pull request Nov 17, 2022 that will close this issue
garyvdm pushed a commit to garyvdm/dbus-ezy that referenced this issue May 9, 2024
Rather than creating a map of {value: enum}, let's just use Foo(value)
to resolve to the respective enum value.

This fixes a regression with introspection introduced in
commit 3282eed "Improve unmarshall performance":

  File "dbus_next/_private/unmarshaller.py", line 247, in _read_header
    self.flag = MESSAGE_FLAG_MAP[buffer[2]]
                ~~~~~~~~~~~~~~~~^^^^^^^^^^^
  KeyError: 0

MESSAGE_FLAG_MAP is built like this:
    MESSAGE_FLAG_MAP = {field.value: field for field in MessageFlag}

But MessageFlag is a IntFlag, so the zero value (NONE) is missing from
the iterator:

  >>> [f for f in dbus_next.constants.MessageFlag]
  [<MessageFlag.NO_REPLY_EXPECTED: 1>, <MessageFlag.NO_AUTOSTART: 2>,
   <MessageFlag.ALLOW_INTERACTIVE_AUTHORIZATION: 4>]

Resolving the enum through the constructor fixes this. MESSAGE_TYPE_MAP
and HEADER_NAME_MAP are changed in solidarity.

Fixes altdesktop#142
garyvdm pushed a commit to garyvdm/dbus-ezy that referenced this issue May 10, 2024
Rather than creating a map of {value: enum}, let's just use Foo(value)
to resolve to the respective enum value.

This fixes a regression with introspection introduced in
commit 3282eed "Improve unmarshall performance":

  File "dbus_next/_private/unmarshaller.py", line 247, in _read_header
    self.flag = MESSAGE_FLAG_MAP[buffer[2]]
                ~~~~~~~~~~~~~~~~^^^^^^^^^^^
  KeyError: 0

MESSAGE_FLAG_MAP is built like this:
    MESSAGE_FLAG_MAP = {field.value: field for field in MessageFlag}

But MessageFlag is a IntFlag, so the zero value (NONE) is missing from
the iterator:

  >>> [f for f in dbus_next.constants.MessageFlag]
  [<MessageFlag.NO_REPLY_EXPECTED: 1>, <MessageFlag.NO_AUTOSTART: 2>,
   <MessageFlag.ALLOW_INTERACTIVE_AUTHORIZATION: 4>]

Resolving the enum through the constructor fixes this. MESSAGE_TYPE_MAP
and HEADER_NAME_MAP are changed in solidarity.

Fixes altdesktop#142
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant