Skip to content

Use a thread-safe container for maps that are accessed concurrently

Since the last release, from time to time I see this:

photo5976424560226053915

Some users have reported the same. Debugging the issue, I see that many threads are waiting on PluginFactory's pluginInfoCache.get() (see below).

I'm not sure if this can be a deadlock we introduced with the new DeviceSettingsFragment (it's the only thing that changed in the last release that shows in the threads waiting).

Also, I'm not sure if a deadlock can result in a busy wait that could use battery like that.

I'm just hoping this patch will help, but not really sure. 🤷

DALVIK THREADS (21):
"Thread-9" prio=5 tid=18 Runnable
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x12f23900 self=0x74878d1800
  | sysTid=22235 nice=0 cgrp=default sched=0/0 handle=0x74867514f0
  | state=R schedstat=( 9344096785 12759679 416 ) utm=934 stm=0 core=6 HZ=100
  | stack=0x748664e000-0x7486650000 stackSize=1041KB
  | held mutexes= "mutator lock"(shared held)
  at java.util.TreeMap.getEntry(TreeMap.java:352)
  at java.util.TreeMap.get(TreeMap.java:279)
  at org.kde.kdeconnect.Plugins.PluginFactory.getPluginInfo(PluginFactory.java:144)
  at org.kde.kdeconnect.Plugins.PluginFactory.getOutgoingCapabilities(PluginFactory.java:212)
  at org.kde.kdeconnect.NetworkPacket.createIdentityPacket(NetworkPacket.java:280)
  at org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider.lambda$broadcastUdpPacket$6(LanLinkProvider.java:395)
  at org.kde.kdeconnect.Backends.LanBackend.-$$Lambda$LanLinkProvider$4xYEbMBPevFn8WvZS7EsJBXFdks.run(lambda:-1)
  at java.lang.Thread.run(Thread.java:764)

"Thread-15" prio=5 tid=19 Runnable
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x1320bb48 self=0x74a2087400
  | sysTid=22241 nice=0 cgrp=default sched=0/0 handle=0x7485dff4f0
  | state=R schedstat=( 9270299327 72720626 1232 ) utm=925 stm=2 core=5 HZ=100
  | stack=0x7485cfc000-0x7485cfe000 stackSize=1041KB
  | held mutexes= "mutator lock"(shared held)
  at java.util.TreeMap.getEntry(TreeMap.java:352)
  at java.util.TreeMap.get(TreeMap.java:279)
  at org.kde.kdeconnect.Plugins.PluginFactory.getPluginInfo(PluginFactory.java:144)
  at org.kde.kdeconnect.Plugins.PluginFactory.getOutgoingCapabilities(PluginFactory.java:212)
  at org.kde.kdeconnect.NetworkPacket.createIdentityPacket(NetworkPacket.java:280)
  at org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider.lambda$broadcastUdpPacket$6(LanLinkProvider.java:395)
  at org.kde.kdeconnect.Backends.LanBackend.-$$Lambda$LanLinkProvider$4xYEbMBPevFn8WvZS7EsJBXFdks.run(lambda:-1)
  at java.lang.Thread.run(Thread.java:764)

"Thread-11" prio=5 tid=20 Runnable
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x12f25840 self=0x74878d4800
  | sysTid=22237 nice=0 cgrp=default sched=0/0 handle=0x74865454f0
  | state=R schedstat=( 9474596242 8205053 182 ) utm=945 stm=2 core=4 HZ=100
  | stack=0x7486442000-0x7486444000 stackSize=1041KB
  | held mutexes= "mutator lock"(shared held)
  at java.lang.String.compareTo(String.java:113)
  at java.util.TreeMap.getEntry(TreeMap.java:353)
  at java.util.TreeMap.get(TreeMap.java:279)
  at org.kde.kdeconnect.Plugins.PluginFactory.getPluginInfo(PluginFactory.java:144)
  at org.kde.kdeconnect.Plugins.PluginFactory.getOutgoingCapabilities(PluginFactory.java:212)
  at org.kde.kdeconnect.NetworkPacket.createIdentityPacket(NetworkPacket.java:280)
  at org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider.lambda$broadcastUdpPacket$6(LanLinkProvider.java:395)
  at org.kde.kdeconnect.Backends.LanBackend.-$$Lambda$LanLinkProvider$4xYEbMBPevFn8WvZS7EsJBXFdks.run(lambda:-1)
  at java.lang.Thread.run(Thread.java:764)

"main" prio=5 tid=1 Runnable
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x747703c8 self=0x74a2014c00
  | sysTid=21597 nice=-10 cgrp=default sched=0/0 handle=0x7528100548
  | state=R schedstat=( 8997586492 93457920 876 ) utm=890 stm=9 core=7 HZ=100
  | stack=0x7ffd8d8000-0x7ffd8da000 stackSize=8MB
  | held mutexes= "mutator lock"(shared held)
  at java.util.TreeMap.getEntry(TreeMap.java:352)
  at java.util.TreeMap.get(TreeMap.java:279)
  at org.kde.kdeconnect.Plugins.PluginFactory.getPluginInfo(PluginFactory.java:144)
  at org.kde.kdeconnect.UserInterface.PluginPreference.<init>(PluginPreference.java:29)
  at org.kde.kdeconnect.UserInterface.DeviceSettingsFragment.lambda$onCreatePreferences$1(DeviceSettingsFragment.java:103)
  at org.kde.kdeconnect.UserInterface.-$$Lambda$DeviceSettingsFragment$WpKZbYAicq6II-H_Imrqt-4WSgs.onServiceStart(lambda:-1)
  at org.kde.kdeconnect.BackgroundService.onStartCommand(BackgroundService.java:384)
  at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3802)
  at android.app.ActivityThread.access$1800(ActivityThread.java:207)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1779)
  at android.os.Handler.dispatchMessage(Handler.java:106)
  at android.os.Looper.loop(Looper.java:193)
  at android.app.ActivityThread.main(ActivityThread.java:6863)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Merge request reports