question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Potential ConcurrentException in MeshNetworkDb:InsertNetworkAsyncTask()

See original GitHub issue

Hello, I’d like to report a second bug found during importing a MeshNetwork (The first one and solution has been post under BubblyNetDev post named “Migration issue in 3.1.5”, not sure if it has been read and is planned to be fixed in next releases).

By the way, In class MeshNetworkDb.Java

Problem :
In class :

private static class InsertNetworkAsyncTask extends AsyncTask<Void, Void, Void> {
    [...]
    if (!meshNetwork.nodes.isEmpty()) {
        nodesDao.insert(meshNetwork.nodes);
    }
 
    if (meshNetwork.groups != null) {
        groupsDao.insert(meshNetwork.groups);
    }
 
    if (meshNetwork.scenes != null) {
        scenesDao.insert(meshNetwork.scenes);
    }
    [...]
}

This can cause troubles down the line, in our case it caused several (still rare) ConcurrentExceptions :

 Fatal Exception: java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$4.done(AsyncTask.java:415)
      ...
 Caused by java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:860)
        at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:95)
        at no.nordicsemi.android.meshprovisioner.data.ProvisionedMeshNodesDao_Impl.insert(ProvisionedMeshNodesDao_Impl.java:303)
        at no.nordicsemi.android.meshprovisioner.MeshNetworkDb$InsertNetworkAsyncTask.doInBackground(MeshNetworkDb.java:307)
        at no.nordicsemi.android.meshprovisioner.MeshNetworkDb$InsertNetworkAsyncTask.doInBackground(MeshNetworkDb.java:271)

Cause : meshNetwork.nodes meshNetwork.groups and meshNetwork.scenes are arrayList. They can be modified from outside the MeshNetworkDb.java for any reason, it shouldn’t happen, but if it happens this leads to ConcurrentException.

Solution I fixed the problem cloning the arrayList before passing it to the Dao, this makes sure we never pass an array which could be potentially modified from outside:

    if (!meshNetwork.nodes.isEmpty()) {
        ArrayList<ProvisionedMeshNode> copyNodes = new ArrayList<>(meshNetwork.nodes);
        nodesDao.insert(copyNodes);
    }

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:45 (23 by maintainers)

github_iconTop GitHub Comments

2reactions
roshanrajaratnamcommented, Feb 14, 2022

I will use the approach that @Mavericksb has suggested since it’s a working solution. All updates and inserts will be done after copying the data in to a new list.

2reactions
Mavericksbcommented, Feb 7, 2022

Any update on this issue? A few of our users are facing something quite similar: at no.nordicsemi.android.mesh.MeshNetworkDb.lambda$insertNetwork$0 (MeshNetworkDb.java:149)

What is the line of code at MeshNetworkDb.java:149 ? If there is an array passed to an insert() method, just copy the array first, and then pass the copy to the insert method instead of the original array, to avoid concurrency.

Read more comments on GitHub >

github_iconTop Results From Across the Web

java.util.ConcurrentModificationException - DigitalOcean
From the output stack trace, it's clear that the concurrent modification exception is thrown when we call iterator next() function.
Read more >
ConcurrentModificationException (Java Platform SE 7 )
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
Read more >
Fix the ConcurrentModificationException | TechTarget
Java's ConcurrentModificationException is thrown when a collection is modified while a Java Iterator is trying to loop through it.
Read more >
Why is a ConcurrentModificationException thrown and how to ...
This will throw a ConcurrentModificationException when the it.hasNext() is called the second time. The correct approach would be. Iterator it = ...
Read more >
How to Avoid the Concurrent Modification Exception in Java
The ConcurrentModificationException in Java occurs when an object is attempted to be modified concurrently without permission.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found