From 5cf86ef7ffb374a8a1d0426b801c97f759375f5d Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 19 Feb 2023 15:59:05 +0100 Subject: [PATCH] Move finally-block to fix deadlock on stop DesktopConnection implements Closeable, so it is implicitly closed after its try-with-resources block. Closing the DesktopConnection shutdowns the sockets, so it is necessary in particular to wake up blocking read() calls from the controller. But the controller thread was joined before the DesktopConnection was closed, causing a deadlock. To fix the problem, join the controller thread only after the DesktopConnection is closed. Refs 400a1c69b198103feff9682895529529890c1acc --- .../java/com/genymobile/scrcpy/Server.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/Server.java b/server/src/main/java/com/genymobile/scrcpy/Server.java index 0aff79bc..4f9fd55f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/Server.java +++ b/server/src/main/java/com/genymobile/scrcpy/Server.java @@ -84,6 +84,8 @@ public final class Server { Workarounds.fillAppInfo(); } + Controller controller = null; + try (DesktopConnection connection = DesktopConnection.open(scid, tunnelForward, control, sendDummyByte)) { VideoCodec codec = options.getCodec(); if (options.getSendDeviceMeta()) { @@ -93,7 +95,6 @@ public final class Server { ScreenEncoder screenEncoder = new ScreenEncoder(codec.getMimeType(), options.getBitRate(), options.getMaxFps(), codecOptions, options.getEncoderName(), options.getDownsizeOnError()); - Controller controller = null; if (control) { controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn()); controller.start(); @@ -114,21 +115,21 @@ public final class Server { if (!IO.isBrokenPipe(e)) { Ln.e("Video encoding error", e); } - } finally { - Ln.d("Screen streaming stopped"); - initThread.interrupt(); - if (controller != null) { - controller.stop(); - } + } + } finally { + Ln.d("Screen streaming stopped"); + initThread.interrupt(); + if (controller != null) { + controller.stop(); + } - try { - initThread.join(); - if (controller != null) { - controller.join(); - } - } catch (InterruptedException e) { - // ignore + try { + initThread.join(); + if (controller != null) { + controller.join(); } + } catch (InterruptedException e) { + // ignore } } }