Skip to content
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

Strict Mode DiskReadViolation on Android when converting Rx Publisher to Flow #1817

Closed
mhernand40 opened this issue Feb 19, 2020 · 3 comments
Labels

Comments

@mhernand40
Copy link

I have some code that is converting an Observable to a Flow in the following manner:

myObservable.toFlowable(BackpressureStrategy.LATEST).asFlow()

I cannot reproduce on my own test device but someone else on my team was able to reproduce the following Strict Mode violation:

android.os.strictmode.DiskReadViolation
        at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1504)
        at java.io.UnixFileSystem.getLength(UnixFileSystem.java:265)
        at java.io.File.length(File.java:970)
        at java.util.zip.ZipFile.<init>(ZipFile.java:212)
        at java.util.zip.ZipFile.<init>(ZipFile.java:152)
        at java.util.jar.JarFile.<init>(JarFile.java:160)
        at java.util.jar.JarFile.<init>(JarFile.java:97)
        at libcore.io.ClassPathURLStreamHandler.<init>(ClassPathURLStreamHandler.java:47)
        at dalvik.system.DexPathList$Element.maybeInit(DexPathList.java:702)
        at dalvik.system.DexPathList$Element.findResource(DexPathList.java:729)
        at dalvik.system.DexPathList.findResources(DexPathList.java:526)
        at dalvik.system.BaseDexClassLoader.findResources(BaseDexClassLoader.java:174)
        at java.lang.ClassLoader.getResources(ClassLoader.java:839)
        at java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:349)
        at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:402)
        at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:488)
        at kotlin.collections.CollectionsKt___CollectionsKt.toCollection(_Collections.kt:1155)
        at kotlin.collections.CollectionsKt___CollectionsKt.toMutableList(_Collections.kt:1188)
        at kotlin.collections.CollectionsKt___CollectionsKt.toList(_Collections.kt:1179)
        at kotlinx.coroutines.reactive.ReactiveFlowKt.<clinit>(ReactiveFlow.kt:138)
        at kotlinx.coroutines.reactive.ReactiveFlowKt.asFlow(Unknown Source:0)

It points to the following top-level property which performs some static initialization within ReactiveFlow.kt:

// ContextInjector service is implemented in `kotlinx-coroutines-reactor` module only.
// If `kotlinx-coroutines-reactor` module is not included, the list is empty.
private val contextInjectors: List<ContextInjector> =
    ServiceLoader.load(ContextInjector::class.java, ContextInjector::class.java.classLoader).toList()
@qwwdfsad qwwdfsad added the bug label Feb 20, 2020
@qwwdfsad
Copy link
Member

This is an improper use of SL on our side. This code is invoked once per application, so as a temporary workaround you can first invoke asFlow from any thread except the main thread

@tclift
Copy link

tclift commented Mar 1, 2021

I think this still occurs, because contextInjectors can be initialised on access. The first access can be an asFlow call from the main thread.

This worked for me as a workaround (near app start):

runBlocking(Dispatchers.IO) {
    Flowable.empty<Void>().asFlow()
}

@yigit
Copy link

yigit commented Mar 17, 2022

I'm not sure if r8 is the right solution here, if coroutines are initialized after the stricty mode is set, this still happens:

To reproduce:

class SomeActivity : AppCompatActivity {
  override fun onCreate(savedInstanceState: Bundle?) {
        StrictMode.setThreadPolicy(
            StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()
                .detectDiskWrites()
                .penaltyDeath()
                .build()
        )
        runBlocking {  } // it will crash here. moving runBlocking above the StrictMode block fixes the issue.
  }
}

Stacktrace:

    java.lang.ExceptionInInitializerError
        at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.initializeDefaultExceptionHandlers(CoroutineExceptionHandlerImpl.kt:27)
        at kotlinx.coroutines.Job.<clinit>(Job.kt:120)
        at kotlinx.coroutines.AbstractCoroutine.<init>(AbstractCoroutine.kt:51)
        at kotlinx.coroutines.BlockingCoroutine.<init>(Builders.kt:66)
        at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:57)
        at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
        at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
        at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
        at SomeActivity.onCreate(SomeActivity.kt:57)
        at android.app.Activity.performCreate(Activity.java:7994)
        at android.app.Activity.performCreate(Activity.java:7978)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants