I began investigating this as we have been seeing some strange crashes, where seemingly the only explanation was our subscriber was invoked after it was disposed (both the observe and the dispose in the main thread).
I have posted an example project here.
https://github.com/stevelilly/rxandroid-racecondition
Tested against rxandroid:2.0.2 + rxjava:2.1.13
This report is based on the belief that when running the following code in the main thread it should
not be possible to reach the exception:
Single.fromCallable(Object::new)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object -> {
throw new IllegalStateException("should never be called");
})
.dispose();
After a few thousand calls I often encounter the exception. More interestingly, in the debugger
we can see that the HandlerScheduler$ScheduledRunnable has already been disposed, yet its run() method is still called.

AFAICT the code in the HandlerScheduler is using removeCallbacks and removeCallbacksAndMessages in the proper way, however it appears it is not safe to call delegate.run() without first checking disposed.
This seems to affect API 24+ much more often than API 23 when I test it, but this could just be the
specific timings of my emulator.
I began investigating this as we have been seeing some strange crashes, where seemingly the only explanation was our subscriber was invoked after it was disposed (both the observe and the dispose in the main thread).
I have posted an example project here.
https://github.com/stevelilly/rxandroid-racecondition
Tested against rxandroid:2.0.2 + rxjava:2.1.13
This report is based on the belief that when running the following code in the main thread it should
not be possible to reach the exception:
After a few thousand calls I often encounter the exception. More interestingly, in the debugger
we can see that the
HandlerScheduler$ScheduledRunnablehas already been disposed, yet itsrun()method is still called.AFAICT the code in the
HandlerScheduleris usingremoveCallbacksandremoveCallbacksAndMessagesin the proper way, however it appears it is not safe to calldelegate.run()without first checkingdisposed.This seems to affect API 24+ much more often than API 23 when I test it, but this could just be the
specific timings of my emulator.