Comments (18)
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.
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.
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.
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.
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.
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.
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.
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.
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.
Thanks so much for putting that together, I will report back tomorrow!
from dbussy.
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.
This example does bus_add
/remove_match_async
, and seems to work OK for me without crashes. Is that helpful to you?
from dbussy.
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.
@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.
Oops, sorry, that comment applied to a different bug. I have no idea why my recent changes would have fixed your problem. :)
from dbussy.
Oh no, the mystery remains!
from dbussy.
@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.
@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)
- StructType inside ArrayType are broken HOT 2
- Cannot return a single value HOT 4
- unregister specific interface HOT 3
- Example of ravel.ManagedObjectsHandler().get_managed_objects(...) HOT 2
- How to strip signatures from arguments HOT 5
- How to pass signatures HOT 4
- Help needed to migrating a wifi agent HOT 8
- Possible examples HOT 1
- Apparently harmless Exception in ravel.py HOT 12
- Openning a connection to a separate D-BUS bus HOT 2
- Support matching on arg0 for ravel's `listen_signal()`
- High CPU usage for `_reaper` HOT 2
- Adding argument of an Array of Dictionaries leads to AttributeError HOT 2
- Exceptions in asynchronous property setting not propagated to the user code HOT 10
- Diagnosis: Name Issue
- Strange behavior on ravel connection object deletion HOT 6
- Should there be a ravel.Connection.listen_signal_async? HOT 1
- Move away from distutils HOT 1
- Trouble sending a message with an argument of type "aay" HOT 2
- Cannot run loop in IDE HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dbussy.