Giter Site home page Giter Site logo

Unable to duplicate bus filter about dbussy HOT 18 CLOSED

ldo avatar ldo commented on June 15, 2024 1
Unable to duplicate bus filter

from dbussy.

Comments (18)

ldo avatar ldo commented on June 15, 2024 1

Glad to hear it. All I did was realize that an explicit PendingCall.cancel() call could cause an exception inside the pending_done callback. It should also cause an exception in the await_reply() call, but that one will be passed back to the caller.

from dbussy.

ldo avatar ldo commented on June 15, 2024

Let me try and understand what you are doing.

Are you opening multiple connections to the same D-Bus daemon? Or are you registering these callbacks on the same connection? I imagine that separate Connection objects would each receive their own copies of appropriately-addressed incoming messages.

If you are registering multiple filters on the same Connection, are you returning DBUS.HANDLER_RESULT_NOT_YET_HANDLED from the handlers? Because DBUS.HANDLER_RESULT_HANDLED will stop the search for further filters.

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

For each instance of the class, I am opening a new connection to the same D-Bus daemon (DBUS.BUS_SYSTEM). For each one I am calling bus_add_match with the same rules, but differing only in the path. All signals that were registered with different path rules are being sent to the first registered filter and match only, and no other instances after that.

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

I recently observed something new. When I switched the signal call back return from HANDLER_RESULT_HANDLED to HANDLER_RESULT_NOT_YET_HANDLED, each instance of the class received the message. This means that the path key is not being properly filtered I'd imagine, and therefore the message is sent to both, even though it should only be sent to the callback that registered the appropriate keys including the sender path. The bus_add_match looks like the following:

self._dbus.bus_add_match({"type": "signal", "interface": "org.freedesktop.DBus.Properties", "member": "PropertiesChanged",
            "arg0": "org.bluez.GattCharacteristic1", "path": char_path})

Where the path looks something like '/org/bluez/hci0/dev_D4_D2_34_E3_BC_C5/service001b/char001f'

Does anything stand out that might indicate why that sender path isn't being filtered correctly?

Thanks!

from dbussy.

ldo avatar ldo commented on June 15, 2024

Just a note that add_filter lets you filter all messages. As for bus_add_match, note that it should do prefix matching if either the message or match path ends with /. The latter doesnโ€™t in your case, but what about the former?

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

I very much appreciate the help! I hadn't discovered bus_add_match_action until now, and it works as expected. I must still be misunderstanding the use of add_filter and bus_add_match.

I am however experiencing a SIGSEGV when attempting to call bus_remove_match_action. I was experiencing the same behavior when trying to use remove_filter. I'm passing it the same rule and func. Thoughts?

from dbussy.

ldo avatar ldo commented on June 15, 2024

Just a note, are you specifying private = True on at least the second Connection.bus_get call? Otherwise libdbus will return a common shared connection object.

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

I was not, I had it set to False, but I have attempted using True with the same result unfortunately. This is occurring with only a single instance as well, regardless of private state.

from dbussy.

ldo avatar ldo commented on June 15, 2024

Here is an example script I put together:

import sys
import os
import asyncio
import dbussy as dbus
from dbussy import \
    DBUS

def get_bool_env(name, default) :
    val = os.environ.get(name, "").lower()
    if default :
        result = not any(val.startswith(c) for c in "0nf")
    else :
        result = any(val.startswith(c) for c in "1yt")
    #end if
    return \
        result
#end get_bool_env

#+
# Mainline
#-

separate_conns = get_bool_env("SEPARATE_CONNS", True)
private_conn = get_bool_env("PRIVATE_CONN", True)
sys.stderr.write("Separate connections: %s; private conn: %s\n" % (separate_conns, private_conn))

loop = asyncio.get_event_loop()

async def mainline() :
    conn1 = await dbus.Connection.bus_get_async(type = DBUS.BUS_SESSION, private = False)
    conn1.enable_receive_message({DBUS.MESSAGE_TYPE_SIGNAL})
    if separate_conns :
        conn2 = await dbus.Connection.bus_get_async(type = DBUS.BUS_SESSION, private = private_conn)
        conn2.enable_receive_message({DBUS.MESSAGE_TYPE_SIGNAL})
        use_conn2 = conn2
    else :
        conn2 = None
        use_conn2 = conn1
    #end if

    await conn1.bus_add_match_async \
      (
        {
            "type" : "signal",
            "interface": "org.freedesktop.DBus.Properties",
            "path" : "/org/bluez/hci0/dev_D4_D2_34_E3_BC_C5/service001b/char001f",
            "arg0": "org.bluez.GattCharacteristic1",
        }
      )
    await use_conn2.bus_add_match_async \
      (
        {
            "type" : "signal",
            "interface": "org.freedesktop.DBus.Properties",
            "path" : "/org/bluez/hci1/dev_D4_D2_34_E3_BC_C5/service001b/char001f",
            "arg0": "org.bluez.GattCharacteristic2",
        }
      )
    to_check = []
    while True :
        if len(to_check) == 0 :
            to_check = [["conn1", conn1]] + ([], [["conn2", conn2]])[conn2 != None]
        #end if
        conn_name, conn = to_check.pop()
        message = await conn.receive_message_async(timeout = 0.25)
        if message != None :
            sys.stderr.write("%s got a message, type %d, serial = %d\n" % (conn_name, message.type, message.serial))
            if message.type == DBUS.MESSAGE_TYPE_METHOD_CALL :
                sys.stderr.write(" destination = %s\n" % repr(message.destination))
            #end if
            if message.type in (DBUS.MESSAGE_TYPE_METHOD_CALL, DBUS.MESSAGE_TYPE_SIGNAL) :
                sys.stderr.write(" path = %s, interface = %s, name = %s\n" % (repr(message.path), repr(message.interface), repr(message.member)))
            #end if
            sys.stderr.write(" contents = %s\n" % repr(list(message.objects)))
            sys.stdout.flush()
        #end if
    #end while
#end mainline

loop.run_until_complete(mainline())

Does that look like it reproduces your situation? By default it opens two bus connections, sets a different filter on each, then sits in a loop polling them for incoming messages. When I run that (without setting any environment variables), and send it signals with commands like

dbus-send --session --type=signal /org/bluez/hci0/dev_D4_D2_34_E3_BC_C5/service001b/char001f org.freedesktop.DBus.Properties.PropertiesChanged string:org.bluez.GattCharacteristic1

and

dbus-send --session --type=signal /org/bluez/hci1/dev_D4_D2_34_E3_BC_C5/service001b/char001f org.freedesktop.DBus.Properties.PropertiesChanged string:org.bluez.GattCharacteristic2

I always get output which indicates that each message was received on exactly the right connection.

Feel free to point out what I have missed.

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

Thanks so much for putting that together, I will report back tomorrow!

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

This certainly works as expected, I now realize that I was incorrectly using add_filter and bus_add_match. I am now accomplishing the same objective with bus_add_match_action, and it works as expected, so all good there.

My only remaining issue now is that I receive a SIGSEGV when attempting to call bus_remove_match_action. It's happening at this line. Please let me know if examining some of the values in that func would help.

from dbussy.

ldo avatar ldo commented on June 15, 2024

This example does bus_add/remove_match_async, and seems to work OK for me without crashes. Is that helpful to you?

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

I've done some more testing and continue to get the SIGSEGV when bus_remove_match_action_async is called when no more match actions are remaining and self.remove_filter(self._rule_action_match, None) is called here. You can see where I am adding and removing the match actions here add#1, add#2 and remove#1, remove#2. Apologies, the code is a bit rough still. I can't see any significant difference in my use and yours.

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

@ldo I am no longer experiencing the seg fault after your latest changes! Thanks so much for continuing to help me. I'll go ahead and close this.

from dbussy.

ldo avatar ldo commented on June 15, 2024

Oops, sorry, that comment applied to a different bug. I have no idea why my recent changes would have fixed your problem. :)

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

Oh no, the mystery remains!

from dbussy.

kent-williams avatar kent-williams commented on June 15, 2024

@ldo This may help narrow down which change solved it.. I am not experiencing the seg fault with the current master, but I am with the current wheel on pypi.

from dbussy.

ldo avatar ldo commented on June 15, 2024

@kent-williams Unfortunately that upload is quite a few months old now. The best way to track the difference down is with git-bisect.

from dbussy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.