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 400a1c69b1
This commit is contained in:
Romain Vimont 2023-02-19 15:59:05 +01:00
parent e02f30f895
commit 5cf86ef7ff

View file

@ -84,6 +84,8 @@ public final class Server {
Workarounds.fillAppInfo(); Workarounds.fillAppInfo();
} }
Controller controller = null;
try (DesktopConnection connection = DesktopConnection.open(scid, tunnelForward, control, sendDummyByte)) { try (DesktopConnection connection = DesktopConnection.open(scid, tunnelForward, control, sendDummyByte)) {
VideoCodec codec = options.getCodec(); VideoCodec codec = options.getCodec();
if (options.getSendDeviceMeta()) { if (options.getSendDeviceMeta()) {
@ -93,7 +95,6 @@ public final class Server {
ScreenEncoder screenEncoder = new ScreenEncoder(codec.getMimeType(), options.getBitRate(), options.getMaxFps(), codecOptions, ScreenEncoder screenEncoder = new ScreenEncoder(codec.getMimeType(), options.getBitRate(), options.getMaxFps(), codecOptions,
options.getEncoderName(), options.getDownsizeOnError()); options.getEncoderName(), options.getDownsizeOnError());
Controller controller = null;
if (control) { if (control) {
controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn()); controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn());
controller.start(); controller.start();
@ -114,21 +115,21 @@ public final class Server {
if (!IO.isBrokenPipe(e)) { if (!IO.isBrokenPipe(e)) {
Ln.e("Video encoding error", e); Ln.e("Video encoding error", e);
} }
} finally { }
Ln.d("Screen streaming stopped"); } finally {
initThread.interrupt(); Ln.d("Screen streaming stopped");
if (controller != null) { initThread.interrupt();
controller.stop(); if (controller != null) {
} controller.stop();
}
try { try {
initThread.join(); initThread.join();
if (controller != null) { if (controller != null) {
controller.join(); controller.join();
}
} catch (InterruptedException e) {
// ignore
} }
} catch (InterruptedException e) {
// ignore
} }
} }
} }