-
Notifications
You must be signed in to change notification settings - Fork 588
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
Crash when trying to connect too fast [UndeliverableException] #383
Comments
Mentioning @uKL |
Then I am not alone. I too have a call to connect again directly from my onConnectionFailure handler because I generally want to re-establish the connection ASAP. E.g. this is the meat of my connection method. val connectionSubscription = device.establishConnection(false)
.observeOn(AndroidSchedulers.mainThread())
.doOnDispose({onDisposeConnectionSubscription(device)})
.subscribe({ onConnectionReceived(device, it) }, { onConnectionFailure(device, it) }) Side note: doOnDispose does not appear to be called in the way doOnUnsubscribe is called in rx1 land. It is in fact not called at all for me, but I have also not looked enough at the RXJava guides to know if it should be. Just in case my trace adds some value, here it is:
|
Could you two write a minimal code that would reproduce the error? |
Maybe. I might try taking the project sample app and modifying it. For me the crashes are not reliably reproducible. It most reliably happens when I: Re-inserting the battery before the phone notices the lost connection can also cause some very "interesting" behavior. |
Thanks, I'll follow up probably early next week. :) |
Hey @guillaumebo, first thing. Here's a morning read for you ReactiveX/RxJava#4811 There is a slight difference between doOnDispose and doFinally. I suppose you should use the latter.
|
Thanks @uKL , I had already asked myself the question of the difference between these two. |
I've seen something similar coming from the inside of the library, I'll try to investigate it. |
We've seen these This happens when you dispose of the subscription while a disconnect takes place. We worked around this by registering an uncaught-exception handler by calling |
You've got the point. However, we'd like to manage the error propagation to verify if emitted errors are in fact ignorable or this was a mistake. We'll issue an update with a fix soon. |
…l changes to emitter based observers were required.
…l changes to emitter based observers were required. (#389)
I tried the 1.5.0 release and 1.6.0-SNAPSHOT and still get this issue: |
@NitroG42 If you subscribe or observe on a different scheduler than the one that is used by the RxAndroidBle connection-handler, you still can get this error. After the fix of this issue, the error may be delivered properly all the way up to your code that calls the RxAndroidBle methods, but if you then continue your Rx-chain on a different Scheduler, you still may wind up with the |
I'm not using others schedulers unfortunatelly... Here's my code, It might help ! (or not): connectionObs = RxClientHolder.rxBleClient.getBleDevice(device.macAdress)
.establishConnection(true)
.retryWhen { errorNotification ->
errorNotification.doOnNext { Timber.e("error during connection, retrying...") }
.delay(2, TimeUnit.SECONDS)
}
.compose(ConnectionSharingAdapter())
.doOnNext { DeviceEvents.connectionStatus.onNext(ConnectionStatus.CONNECTED) }
connectDisposable?.dispose()
connectDisposable = connectionObs!!.flatMap { rxBleConnection ->
val monitoringData = device.monitoringData!!
val configData = device.configData!!
Single.zip(
listOf(
rxBleConnection.readCharacteristic(Device3UUID.MONITORING.CHAR_TEMP).doOnSuccess(
monitoringData::updateTemp
),
rxBleConnection.readCharacteristic(Device3UUID.MONITORING.CHAR_BATT).doOnSuccess(
monitoringData::updateBatt
),
rxBleConnection.readCharacteristic(Device3UUID.MONITORING.CHAR_USB).doOnSuccess(
monitoringData::updateUsb
),
rxBleConnection.readCharacteristic(Device3UUID.CONFIG.CHAR_LED).doOnSuccess(
configData::updateLed
)
), { raw: Array<Any> ->
}).flatMapObservable {
Observable.combineLatest(
listOf(
rxBleConnection.setupNotification(Device3UUID.MONITORING.CHAR_BATT).flatMap { it }.doOnNext(
monitoringData::updateBatt
),
rxBleConnection.setupNotification(Device3UUID.MONITORING.CHAR_TEMP).flatMap { it }.doOnNext(
monitoringData::updateTemp
),
rxBleConnection.setupNotification(Device3UUID.MONITORING.CHAR_USB).flatMap { it }.doOnNext(
monitoringData::updateUsb
),
rxBleConnection.setupNotification(Device3UUID.CONFIG.CHAR_LED).flatMap { it }.doOnNext(
configData::updateLed
)
), { raw: Array<Any> ->
Timber.d("received notification")
raw
})
}
}
.doAfterTerminate { DeviceEvents.connectionStatus.onNext(ConnectionStatus.DISCONNECTED) }
.subscribe({
}, {
Timber.e(it, "onErrorConnection")
}) The issue occurs because I plug my ble device (with usb), and it's triggers a forced reboot, then the crash occurs. |
Here's the log with the exception :
|
@NitroG42 Does it happen everytime you process this scenario? What is the device you are testing on? |
It happens randomly when the device is disconnected, either by usb or sometime randomly when we are connected to it. |
@NitroG42 Snapshot 1.6.0 is rolling (will be available soon). Could you try it out? |
I will try, I'll update the thread when I have news. |
I still got the issue, I can trigger it just by disposing my connectDisposable (see above, it's the result of the subscribe that connect using ConnectionSharingAdapter, and readChara):
|
I really struggle to reproduce your issue. I've used exactly your code and it's working flawlessly. Are you able to prepare a minimum mode to reproduce the issue, so I can run it in my Android Studio? Can you also try without the @guillaumebo @eimermusic How about you Guys? Do you still see it? |
I just tried with the last 1.6 Snapshot, it's seems to work better ! |
Yes, the warning is expected, I wanted to see if it is handled correctly. I'll remove/mask it before a release. Great news! |
I just encountered the same error, but with a different stack trace (I'm on version
It seems to me this may be caused due to the isDisposed() check being done prematurely, and that this could be fixed by additionally moving the check into the callback (onError etc) or replacing it with |
having same issue too
|
@uKL , the bug that @guillaumebo reported(below) we also have it from time to time(starting from version 1.4.1) and my goal for next sprint is to investigate this(starting today).
|
Hello,
|
I don't know if it's linked, but i noticed this error in log (not app crash, it's correctly handled) during a connection lost (ble device turned off)
I have no more crash with latest update for this moment on my side |
@guillaumebo which version are u using? |
The rx2 1.6 Snapshot |
I have the same problem, but in another place (
Version 1.6.0-SNAPSHOT (but bug appears also in 1.5.0-SNAPSHOT) |
I confirmed that this still happened w/
I temporarily set up an RxJava hook like below to workaround it: class SetUpRxJavaErrorHandler() {
operator fun invoke() = RxJavaPlugins.setErrorHandler({ error ->
when {
error is UndeliverableException && error.cause is BleDisconnectedException ->
workaroundRxAndroidBleIssue(error)
else -> throw error
}
})
private fun workaroundRxAndroidBleIssue(error: Throwable) {
Log.e(TAG, "Encountered https://github.com/Polidea/RxAndroidBle/issues/383", error)
}
} |
Hello everyone, I was investigating this issue recently. The root cause of the problem is the threading of Android OS — callbacks may be called on arbitrary threads. One of the differences between KotlinRxJavaPlugins.setErrorHandler({ error ->
if (error is UndeliverableException && error.cause is BleException) {
return // ignore BleExceptions as they were surely delivered at least once
}
// add other custom handlers if needed
throw error
}) JavaRxJavaPlugins.setErrorHandler(error -> {
if (error instanceof UndeliverableException && error.cause instanceof BleException) {
return; // ignore BleExceptions as they were surely delivered at least once
}
// add other custom handlers if needed
throw error;
}); |
@dariuszseweryn Where do you place that code for the workaround? Maybe inside your Applicatio class? |
Basically anywhere. |
Don't really know what I'm talking about here, but this says that RxJavaPlugins have been deprecated in favor of RxJavaHooks. The relevant one would seem to be |
That link seems to be relevant to RxJava 1.x only. The Java doc for RxJavaPlugins of RxJava 2.x has no depreciation on the class http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/plugins/RxJavaPlugins.html. |
@DariuszAniszewski I can't seem to compile the workaround, since |
Hello @cuiti |
@cuiti Yes that is right. You get an unhandled exception when you try to rethrow the error in Java. I'm using the folowing in my project: RxJavaPlugins.setErrorHandler(error -> {
if (error instanceof UndeliverableException && error.getCause() instanceof BleException) {
return; // ignore BleExceptions as they were surely delivered at least once
} else {
throw new Exception(error);
}
}); |
based on this doc it would be nice if the library avoid the exceptions like this
|
Thank you for the suggestion. If the user creates a single This approach needs to get evaluated. |
Greetings I am getting the same issues as described above in version 1.8.1. |
No. At least not yet.
Partially. I do not have enough time to develop a new API that could allow for elimination the |
lib version 1.5 rx2
I am facing issue in my app and in the sample app but i cannot find where the issue source is.
To reproduce, it's really easy, you have to try a connection just right after reactivate Bluetooth on the device (about 1 sec after). I think the GATT stack is not really ready but in fact it throw a disconnection although the connection process is not done. it's seems that a exception is not handle and rx is not happy but i am not sure.
logs :
The text was updated successfully, but these errors were encountered: