From 912c431511b3b71550889f03c4f421759bafff63 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 17 Mar 2023 14:21:00 +0000 Subject: [PATCH] fix(debugger): process UI updates in correct thread (#1796) --- .../gui/device/debugger/DebugController.java | 30 ++++---- .../java/jadx/gui/ui/dialog/ADBDialog.java | 34 ++++----- .../jadx/gui/ui/panel/JDebuggerPanel.java | 74 ++++++++++--------- 3 files changed, 72 insertions(+), 66 deletions(-) diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/DebugController.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/DebugController.java index 86a206d4..129b4a91 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/DebugController.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/DebugController.java @@ -14,12 +14,10 @@ import java.util.concurrent.Executors; import javax.swing.JOptionPane; import javax.swing.tree.DefaultMutableTreeNode; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.reactivex.annotations.NonNull; -import io.reactivex.annotations.Nullable; - import jadx.core.dex.info.FieldInfo; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.nodes.ClassNode; @@ -42,6 +40,7 @@ import jadx.gui.ui.panel.JDebuggerPanel; import jadx.gui.ui.panel.JDebuggerPanel.IListElement; import jadx.gui.ui.panel.JDebuggerPanel.ValueTreeNode; import jadx.gui.utils.NLS; +import jadx.gui.utils.UiUtils; public final class DebugController implements SmaliDebugger.SuspendListener, IDebugController { @@ -78,7 +77,7 @@ public final class DebugController implements SmaliDebugger.SuspendListener, IDe initTypeMap(); } this.debuggerPanel = debuggerPanel; - debuggerPanel.resetUI(); + UiUtils.uiRunAndWait(debuggerPanel::resetUI); try { debugger = SmaliDebugger.attach(adbHost, adbPort, this); } catch (SmaliDebuggerException e) { @@ -251,7 +250,6 @@ public final class DebugController implements SmaliDebugger.SuspendListener, IDe throw new JadxRuntimeException("Unexpected type: " + type); } - @NonNull protected static RuntimeType castType(String type) { RuntimeType rt = null; if (!StringUtils.isEmpty(type)) { @@ -663,22 +661,22 @@ public final class DebugController implements SmaliDebugger.SuspendListener, IDe } private void updateAllRegisters(FrameNode frame) { - if (buildRegTreeNodes(frame).size() > 0) { - fetchAllRegisters(frame); - } + UiUtils.uiRun(() -> { + if (!buildRegTreeNodes(frame).isEmpty()) { + fetchAllRegisters(frame); + } + }); } private void fetchAllRegisters(FrameNode frame) { List regs = cur.regAdapter.getInitializedList(frame.getCodeOffset()); for (SmaliRegister reg : regs) { - lazyQueue.execute(() -> { - Entry info = cur.regAdapter.getInfo(reg.getRuntimeRegNum(), frame.getCodeOffset()); - RegTreeNode regNode = frame.getRegNodes().get(reg.getRegNum()); - if (info != null) { - applyDbgInfo(regNode, info); - } - updateRegister(regNode, null, true); - }); + Entry info = cur.regAdapter.getInfo(reg.getRuntimeRegNum(), frame.getCodeOffset()); + RegTreeNode regNode = frame.getRegNodes().get(reg.getRegNum()); + if (info != null) { + applyDbgInfo(regNode, info); + } + updateRegister(regNode, null, true); } } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/dialog/ADBDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/dialog/ADBDialog.java index 991774d3..c3eff176 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/dialog/ADBDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/dialog/ADBDialog.java @@ -475,28 +475,28 @@ public class ADBDialog extends JDialog implements ADB.DeviceStateListener, ADB.J LOG.error("Failed to find device", e); return; } - node.tNode.removeAllChildren(); - DefaultMutableTreeNode tempNode = null; - for (String s : procList) { - DefaultMutableTreeNode pnode = new DefaultMutableTreeNode(s); - node.tNode.add(pnode); - if (!debugSetter.expectPkg.isEmpty() && s.endsWith(debugSetter.expectPkg)) { - if (debugSetter.autoAttachPkg && debugSetter.device.equals(node.device)) { - debugSetter.set(node.device, debugSetter.ver, getPid(s), s); - if (attachProcess(mainWindow)) { - dispose(); - return; + + SwingUtilities.invokeLater(() -> { + node.tNode.removeAllChildren(); + DefaultMutableTreeNode foundNode = null; + for (String procStr : procList) { + DefaultMutableTreeNode pnode = new DefaultMutableTreeNode(procStr); + node.tNode.add(pnode); + if (!debugSetter.expectPkg.isEmpty() && procStr.endsWith(debugSetter.expectPkg)) { + if (debugSetter.autoAttachPkg && debugSetter.device.equals(node.device)) { + debugSetter.set(node.device, debugSetter.ver, getPid(procStr), procStr); + if (attachProcess(mainWindow)) { + dispose(); + return; + } } + foundNode = pnode; } - tempNode = pnode; } - } - DefaultMutableTreeNode theNode = tempNode; - SwingUtilities.invokeLater(() -> { procTreeModel.reload(node.tNode); procTree.expandPath(new TreePath(node.tNode.getPath())); - if (theNode != null) { - TreePath thePath = new TreePath(theNode.getPath()); + if (foundNode != null) { + TreePath thePath = new TreePath(foundNode.getPath()); procTree.scrollPathToVisible(thePath); procTree.setSelectionPath(thePath); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java b/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java index 5aef0fd1..d98006f1 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java @@ -88,6 +88,7 @@ public class JDebuggerPanel extends JPanel { private transient KeyEventDispatcher controllerShortCutDispatcher; public JDebuggerPanel(MainWindow mainWindow) { + UiUtils.uiThreadGuard(); this.mainWindow = mainWindow; controller = new DebugController(); this.setLayout(new BorderLayout()); @@ -287,24 +288,26 @@ public class JDebuggerPanel extends JPanel { @Override public void onStateChanged(boolean suspended, boolean stopped) { - if (!stopped) { - if (isGray) { - stop.putValue(Action.SMALL_ICON, ICON_STOP); + UiUtils.uiRun(() -> { + if (!stopped) { + if (isGray) { + stop.putValue(Action.SMALL_ICON, ICON_STOP); + } + } else { + stop.putValue(Action.SMALL_ICON, ICON_STOP_GRAY); + run.putValue(Action.SMALL_ICON, ICON_RUN); + run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run")); + isGray = true; + return; } - } else { - stop.putValue(Action.SMALL_ICON, ICON_STOP_GRAY); - run.putValue(Action.SMALL_ICON, ICON_RUN); - run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run")); - isGray = true; - return; - } - if (suspended) { - run.putValue(Action.SMALL_ICON, ICON_RUN); - run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run")); - } else { - run.putValue(Action.SMALL_ICON, ICON_PAUSE); - run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.pause")); - } + if (suspended) { + run.putValue(Action.SMALL_ICON, ICON_RUN); + run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.run")); + } else { + run.putValue(Action.SMALL_ICON, ICON_PAUSE); + run.putValue(Action.SHORT_DESCRIPTION, NLS.str("debugger.pause")); + } + }); } }); @@ -387,16 +390,18 @@ public class JDebuggerPanel extends JPanel { public boolean showDebugger(String procName, String host, int port, int androidVer, ADBDevice device, String pid) { boolean ok = controller.startDebugger(this, host, port, androidVer); if (ok) { - log(String.format("Attached %s %s:%d", procName, host, port)); - try { - logcatPanel.init(device, pid); - } catch (Exception e) { - log(NLS.str("logcat.error_fail_start")); - LOG.error("Logcat failed to start", e); - } - leftSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerStackFrameSplitterLoc()); - rightSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerVarTreeSplitterLoc()); - mainWindow.showDebuggerPanel(); + UiUtils.uiRun(() -> { + log(String.format("Attached %s %s:%d", procName, host, port)); + try { + logcatPanel.init(device, pid); + } catch (Exception e) { + log(NLS.str("logcat.error_fail_start")); + LOG.error("Logcat failed to start", e); + } + leftSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerStackFrameSplitterLoc()); + rightSplitter.setDividerLocation(mainWindow.getSettings().getDebuggerVarTreeSplitterLoc()); + mainWindow.showDebuggerPanel(); + }); } return ok; } @@ -414,6 +419,8 @@ public class JDebuggerPanel extends JPanel { } public void loadSettings() { + UiUtils.uiThreadGuard(); + Font font = mainWindow.getSettings().getFont(); variableTree.setFont(font.deriveFont(font.getSize() + 1.f)); variableTree.setRowHeight(-1); @@ -423,6 +430,8 @@ public class JDebuggerPanel extends JPanel { } public void resetUI() { + UiUtils.uiThreadGuard(); + thisTreeNode.removeAllChildren(); regTreeNode.removeAllChildren(); @@ -464,12 +473,11 @@ public class JDebuggerPanel extends JPanel { } public void refreshThreadBox(List elements) { - if (elements.size() > 0) { - DefaultComboBoxModel model = - (DefaultComboBoxModel) threadBox.getModel(); - elements.forEach(model::addElement); - } - SwingUtilities.invokeLater(() -> { + UiUtils.uiRun(() -> { + if (!elements.isEmpty()) { + DefaultComboBoxModel model = (DefaultComboBoxModel) threadBox.getModel(); + elements.forEach(model::addElement); + } threadBox.updateUI(); stackFrameList.setFont(mainWindow.getSettings().getFont()); }); -- GitLab