Skip to content

Commit

Permalink
fix(debugger): process UI updates in correct thread (#1796)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Mar 17, 2023
1 parent 5d6b827 commit 912c431
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
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;
Expand All @@ -42,6 +40,7 @@
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 {

Expand Down Expand Up @@ -78,7 +77,7 @@ public boolean startDebugger(JDebuggerPanel debuggerPanel, String adbHost, int a
initTypeMap();
}
this.debuggerPanel = debuggerPanel;
debuggerPanel.resetUI();
UiUtils.uiRunAndWait(debuggerPanel::resetUI);
try {
debugger = SmaliDebugger.attach(adbHost, adbPort, this);
} catch (SmaliDebuggerException e) {
Expand Down Expand Up @@ -251,7 +250,6 @@ private RuntimeType castType(ArgType type) {
throw new JadxRuntimeException("Unexpected type: " + type);
}

@NonNull
protected static RuntimeType castType(String type) {
RuntimeType rt = null;
if (!StringUtils.isEmpty(type)) {
Expand Down Expand Up @@ -663,22 +661,22 @@ private void updateAllFieldValues(long thisID, FrameNode frame) {
}

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<SmaliRegister> regs = cur.regAdapter.getInitializedList(frame.getCodeOffset());
for (SmaliRegister reg : regs) {
lazyQueue.execute(() -> {
Entry<String, String> 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<String, String> 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);
}
}

Expand Down
34 changes: 17 additions & 17 deletions jadx-gui/src/main/java/jadx/gui/ui/dialog/ADBDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -475,28 +475,28 @@ public void jdwpProcessOccurred(ADBDevice device, Set<String> id) {
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);
}
Expand Down
74 changes: 41 additions & 33 deletions jadx-gui/src/main/java/jadx/gui/ui/panel/JDebuggerPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -287,24 +288,26 @@ public void actionPerformed(ActionEvent e) {

@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"));
}
});
}
});

Expand Down Expand Up @@ -387,16 +390,18 @@ private void stackFrameSelected(Point p) {
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;
}
Expand All @@ -414,6 +419,8 @@ public int getRightSplitterLocation() {
}

public void loadSettings() {
UiUtils.uiThreadGuard();

Font font = mainWindow.getSettings().getFont();
variableTree.setFont(font.deriveFont(font.getSize() + 1.f));
variableTree.setRowHeight(-1);
Expand All @@ -423,6 +430,8 @@ public void loadSettings() {
}

public void resetUI() {
UiUtils.uiThreadGuard();

thisTreeNode.removeAllChildren();
regTreeNode.removeAllChildren();

Expand Down Expand Up @@ -464,12 +473,11 @@ public void updateThisFieldNodes(List<? extends ValueTreeNode> nodes) {
}

public void refreshThreadBox(List<? extends IListElement> elements) {
if (elements.size() > 0) {
DefaultComboBoxModel<IListElement> model =
(DefaultComboBoxModel<IListElement>) threadBox.getModel();
elements.forEach(model::addElement);
}
SwingUtilities.invokeLater(() -> {
UiUtils.uiRun(() -> {
if (!elements.isEmpty()) {
DefaultComboBoxModel<IListElement> model = (DefaultComboBoxModel<IListElement>) threadBox.getModel();
elements.forEach(model::addElement);
}
threadBox.updateUI();
stackFrameList.setFont(mainWindow.getSettings().getFont());
});
Expand Down

0 comments on commit 912c431

Please sign in to comment.