Skip to content

Commit

Permalink
Do not interrupt cleanup configuration
Browse files Browse the repository at this point in the history
Some options, such as --show-touches or --stay-awake, modify Android
settings and must be restored upon exit.

If scrcpy terminates (e.g. due to an early error) in the middle of the
clean up configuration, the device may be left in an inconsistent state
(some settings might be changed but not restored).

This issue can be reproduced with high probability by forcing scrcpy to
fail:

    scrcpy --show-touches --video-encoder=fail

To prevent this problem, ensure that the clean up thread is not
interrupted until the clean up process is started.

Refs #5601 <#5601>
PR #5613 <#5613>
  • Loading branch information
rom1v committed Dec 8, 2024
1 parent 6c6607d commit 2780e0b
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions server/src/main/java/com/genymobile/scrcpy/CleanUp.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public final class CleanUp {
private boolean pendingRestoreDisplayPower;

private Thread thread;
private boolean interrupted;

private CleanUp(Options options) {
thread = new Thread(() -> runCleanUp(options), "cleanup");
Expand All @@ -34,8 +35,10 @@ public static CleanUp start(Options options) {
return new CleanUp(options);
}

public void interrupt() {
thread.interrupt();
public synchronized void interrupt() {
// Do not use thread.interrupt() because only the wait() call must be interrupted, not Command.exec()
interrupted = true;
notify();
}

public void join() throws InterruptedException {
Expand Down Expand Up @@ -97,15 +100,13 @@ private void runCleanUp(Options options) {

try {
run(displayId, restoreStayOn, disableShowTouches, powerOffScreen, restoreScreenOffTimeout);
} catch (InterruptedException e) {
// ignore
} catch (IOException e) {
Ln.e("Clean up I/O exception", e);
}
}

private void run(int displayId, int restoreStayOn, boolean disableShowTouches, boolean powerOffScreen, int restoreScreenOffTimeout)
throws IOException, InterruptedException {
throws IOException {
String[] cmd = {
"app_process",
"/",
Expand All @@ -126,8 +127,15 @@ private void run(int displayId, int restoreStayOn, boolean disableShowTouches, b
int localPendingChanges;
boolean localPendingRestoreDisplayPower;
synchronized (this) {
while (pendingChanges == 0) {
wait();
while (!interrupted && pendingChanges == 0) {
try {
wait();
} catch (InterruptedException e) {
throw new AssertionError("Clean up thread MUST NOT be interrupted");
}
}
if (interrupted) {
break;
}
localPendingChanges = pendingChanges;
localPendingRestoreDisplayPower = pendingRestoreDisplayPower;
Expand Down

0 comments on commit 2780e0b

Please sign in to comment.