Handle timeout required by sdbus API#73
Conversation
|
Hello @ofacklam I am aware that the sd-bus timeout is not implemented correctly right now: #53 (reply in thread) However, I want to do more research in to how it is best to integrate with Python asyncio in a generic way. |
|
Hi @igo95862 ! Thanks for the quick reply and for the library in general, really handy! Personally I didn't see any other way to integrate this with asyncio. If I understand correctly, the problem is not that you want to control the asyncio event loop's select policy, but rather you want to tell it to call your However I would be glad to discuss other solutions as well :) In our current project we are using the library with this patch since we were running into issues with the newer version 0.12.0. There are cases were both |
|
I didn't know there was a deadlock which makes it a much bigger issue. Looking at the sd-bus source code: Looks like
I wonder why calling the |
|
Looking at the code again, it seems I did some synchronous calls on the same connection previously (a kind of app initialization logic) before starting the async calls. That might be the reason behind the strange behavior, and I guess it's not really an expected use case. So the issue is probably less severe than I thought. Still I would argue that relying on an implementation detail of sdbus regarding timing behavior seems somewhat dangerous. |
Is there some initialization that cannot be done with async code? Will the deadlock still happen if all code is properly async? I will look in to this timeout integration this weekend. I have a few ideas how to make it more native. |
|
I looked in to the Linux APIs and asyncio and I have an interesting idea that I want to try. I also want to setup benchmarks. One of my concerns is that constantly arming and disarming asyncio timer handles will have a negative effect on performance. |
|
I added initial benchmarks in 7e970a6. There definitely is performance impact of this change: Before: After: My plan is to use |
|
Your approach with |
|
I created initial draft in 6bee560. @ofacklam could you give it a test. The performance impact seems to be much smaller: I also added a test there I set bus timeout value to 0.01 seconds and check that the Would be interesting adding a test that replicates your deadlock. |
|
Hi @igo95862 I cherry-picked your commit 6bee560 onto the 0.12.0 release. With this change, my "deadlock" seems to have disappeared, so it solves the problem just as well as my proposal 🎉 Regarding normal timeouts of method calls, I can't forcibly reproduce it on my end (it only happens due to very rare hardware issues), however your unit test seems to cover that quite well. Thanks for that fix, it looks really nice! Just one note: you rely on timerfd == 0 for checking whether it's initialized. Are you sure 0 can never be a valid timerfd value? |
Looks like if you close stdin file descriptor 0 then 0 can be reused for any other file descriptor so it definitely can be an issue. I originally wanted to use -1 but I encountered issues reliably setting that in SdBus init method. I will revisit this before releasing final version. |
|
I added a I think I try to make more progress this week and release the 0.12.1 soon with this fix. |
|
Alright I merged the fe49edb that addresses the bus timeouts. |
|
The latest commit looks very nice, I'm looking forward to testing with it. |
|
I will probably switch to the |
This PR adds correct handling of the timeout behavior mandated by the sdbus API.
According to the docs, two conditions must be met:
However, since
loop.add_readerdoesn't support a timeout parameter, we create a separate timeout event withloop.call_later.More precisely, depending on the return value of
sd_bus_get_timeout():UINT64_MAX: no timeout is created0: processing called immediately withloop.call_soonloop.call_later