Closed mvglasow closed 3 years ago
I see the following threads waiting for something:
Daemon Thread [Timer-0] (Suspended)
waiting for: TaskQueue (id=58)
Thread [AWT-EventQueue-1] (Suspended)
waiting for: ODAPanel (id=59)
ODAPanel.update() line: 37
MainWindow$3$1.run() line: 503
Daemon Thread [HSQLDB Timer @4fb64261] (Suspended)
waiting for: HsqlTimer$TaskQueue (id=57)
Thread [RDSSurveyor-MainWindow-updater] (Suspended)
waiting for: MainWindow (id=60)
MainWindow$3.run() line: 468
Daemon System Thread [Finalizer] (Suspended)
waiting for: ReferenceQueue$Lock (id=62)
Daemon System Thread [Reference Handler] (Suspended)
waiting for: Reference$Lock (id=63)
Daemon System Thread [Java2D Disposer] (Suspended)
waiting for: ReferenceQueue$Lock (id=64)
System Thread [AWT-Shutdown] (Suspended)
waiting for: Object (id=65)
The Daemon System Threads only showed up after suspending the VM, hence they are probably not relevant.
AWT-EventQueue-1
is stuck at the start of ODAPanel.update()
, which is synchronized with the ODAPanel
instance. This is part of a Runnable placed there via SwingUtilities.invokeLater()
; the scheduling happens in RDSSurveyor-MainWindow-updater
, inside a block synchronized to the MainWindow
instance.
RDSSurveyor-MainWindow-updater
is waiting for MainWindow
.
Then there’s two timer threads waiting for their task queues—probably normal behavior for a timer when no task is currently running. AWT-Shutdown
waiting for an object looks like AWT waiting for the main window to be closed before cleaning up and exiting—looks pretty regular to me.
On a rerun, AWT-EventQueue-1
is now waiting for MainWindow
, not ODAPanel
. Both are now held by the RDS-Worker
thread. A call stack reveals that the worker thread invokes MainWindow#windowUpdaterVisitor()
, which updates the application window with new RDS data on the calling thread. Upon visiting a StationTuned
, it locks MainWindow
, and in that block, it updates some data, including a call to ODAPanel#setStation()
(which causes it to obtain a lock on ODAPanel
as well). Similar situations could arise with RTPanel
.
At this point I wondered if it makes sense to move these things into the AWT thread. I tried, and it seems to work—no more deadlocks. Wait for the PR…
Steps to reproduce:
-infile
or selecting it from the GUI)Expected result:
The next hunk of RDS data is processed and data appears in the app window.
Actual result:
RDS Surveyor freezes completely.
Versions used:
88d0bb0, as well as an earlier one, on Ubuntu 20.04, OpenJDK 8.
Additional information:
I suspect this is a long-standing thread sync issue, which has started to manifest only now because of some external change, but has been in the code for very long.
This occurs regardless of whether “Simulate real time” is selected or not. I have only recently upgraded to Ubuntu 20.04 (from 18.04)—while I have used RDS Surveyor only infrequently since then, I have not noticed this issue on 18.04 (I did have sporadic freezes but cannot remember if they were related). On 20.04 I can reliably reproduce the bug.
The bug has so far only occurred with data read from a file (I have only tried
HexFileGroupReader
). When reading live input from a RTL2832U or a Si470x tuner, I can listen to the radio, view RDS data and change stations.When RDS Surveyor is frozen, it does not seem to generate any significant processor load—this appears to be a deadlock rather than an endless loop, probably a thread sync issue.
The same thing happens when I run RDS Surveyor from inside Eclipse—either using “Run” or “Debug”. Call stack while running:
Call stack after suspending the VM: