-
-
Notifications
You must be signed in to change notification settings - Fork 84
create new DeviceListReceived event to avoid race conditions in short–lived client applications #760
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
base: master
Are you sure you want to change the base?
Conversation
Just trying to make sure I understand this PR, is this to let the user know that all DeviceAdded/DeviceRemoved events have happened at the beginning of a connection session? 'cause there's no way to call RequestDeviceList otherwise. The assumption is currently that, after the connect call exits, you can assume all connected devices are in the client's devices list, and the DeviceAdded calls there were just a formality. |
The assumption is currently that, after the connect call exits, you can assume all connected devices are in the client's devices list
I assumed so as well, but, this is not the case. There's a race condition between when the internal event loop processes the HandleDeviceList event and the call exits. Another way of fixing this would be to pass a oneshot tx into the HandleDeviceList event and waiting on the rx end.
|
As I have stated, the current approach works for long–running applications that connect once and can spare the time to wait for events, but not clients that connect, set state, and exit without waiting. |
Not sure I understand how this works? If you disconnect a client after setting state, all devices should stop? What's the use case here? |
The devices list is empty when you connect because buttplug/buttplug/src/client/mod.rs Line 360 in d3247fb
2 approaches to fix this:
this PR implements approach A, but approach B would also be easy to implement, and wouldn't require a minor version bump Edit: upon a second review it seems that approach B is much harder to implement actually |
Got it, thanks. I'm digging into this is because the library has a bunch of huge changes coming up (see the Granted almost no one uses the rust client anyways so I also rarely get feedback on that heh. Anyways, I'll see if there's some way to at least ensure we have devices when connect() returns, though I'll have to make sure of what the best way to do that is in relation to the new work that's come in on |
tysm for all the work! |
i've drawn a diagram illustrating the issue |
The Problem
Currently, the response handling for the
DeviceListRequest
call emits an internal event which is processed asynchronously, and can not be awaited for in the crate's public API. This forces clients to wait forDeviceAdded
events to know when to actually start using the client. The internal implementation looks like this:buttplug/buttplug/src/client/client_event_loop.rs
Lines 308 to 318 in d3247fb
This is not ideal, as a client application will not be notified about when the device list is received if there are no devices connected. A workaround for this is just to
sleep()
for a while to make sure the event is handled. This is fragile and slow for reasons that I do not think require explaining.The Solution
The solution I propose in this PR is to add a
DeviceListReceived
event that client applications may listen toin order to ascertain that devices have been enumerated:
This event is emitted by the previously mentioned internal event loop, after all the
DeviceAdded
events have been dispatched:This PR would require a minor version bump as the events enum is not marked
#[non_exhaustive]
. Consider doing that too.Extras
.device_list_received()
fn
on theButtplugClient
object that returns whether a device list has been received or not