Configure clean up actions dynamically
Some actions may be performed when scrcpy exits, currently: - disable "show touches" - restore "stay on while plugged in" - power off screen - restore "power mode" (to disable "turn screen off") They are performed from a separate process so that they can be executed even when scrcpy-server is killed (e.g. if the device is unplugged). The clean up actions to perform were configured when scrcpy started. Given that there is no method to read the current "power mode" in Android, and that "turn screen off" can be applied at any time using an scrcpy shortcut, there was no way to determine if "power mode" had to be restored on exit. Therefore, it was always restored to "normal", even when not necessary. However, setting the "power mode" is quite fragile on some devices, and may cause some issues, so it is preferable to call it only when necessary (when "turn screen off" has actually been called). For that purpose, make the scrcpy-server main process and the clean up process communicate the actions to perform over a pipe (stdin/stdout), so that they can be changed dynamically. In particular, when the power mode is changed at runtime, notify the clean up process. Refs 1beec99f8283713b1fbf0b3704eb4dceecc9a590 Refs #4456 <https://github.com/Genymobile/scrcpy/issues/4456> Refs #4624 <https://github.com/Genymobile/scrcpy/issues/4624> PR #4649 <https://github.com/Genymobile/scrcpy/pull/4649>
This commit is contained in:
parent
be3f949aa5
commit
9efa162949
@ -1,11 +1,8 @@
|
|||||||
package com.genymobile.scrcpy;
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.util.Base64;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the cleanup of scrcpy, even if the main process is killed.
|
* Handle the cleanup of scrcpy, even if the main process is killed.
|
||||||
@ -14,127 +11,59 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public final class CleanUp {
|
public final class CleanUp {
|
||||||
|
|
||||||
// A simple struct to be passed from the main process to the cleanup process
|
private static final int MSG_TYPE_MASK = 0b11;
|
||||||
public static class Config implements Parcelable {
|
private static final int MSG_TYPE_RESTORE_STAY_ON = 0;
|
||||||
|
private static final int MSG_TYPE_DISABLE_SHOW_TOUCHES = 1;
|
||||||
|
private static final int MSG_TYPE_RESTORE_NORMAL_POWER_MODE = 2;
|
||||||
|
private static final int MSG_TYPE_POWER_OFF_SCREEN = 3;
|
||||||
|
|
||||||
public static final Creator<Config> CREATOR = new Creator<Config>() {
|
private static final int MSG_PARAM_SHIFT = 2;
|
||||||
@Override
|
|
||||||
public Config createFromParcel(Parcel in) {
|
private final OutputStream out;
|
||||||
return new Config(in);
|
|
||||||
|
public CleanUp(OutputStream out) {
|
||||||
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static CleanUp configure(int displayId) throws IOException {
|
||||||
public Config[] newArray(int size) {
|
String[] cmd = {"app_process", "/", CleanUp.class.getName(), String.valueOf(displayId)};
|
||||||
return new Config[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int FLAG_DISABLE_SHOW_TOUCHES = 1;
|
|
||||||
private static final int FLAG_RESTORE_NORMAL_POWER_MODE = 2;
|
|
||||||
private static final int FLAG_POWER_OFF_SCREEN = 4;
|
|
||||||
|
|
||||||
private int displayId;
|
|
||||||
|
|
||||||
// Restore the value (between 0 and 7), -1 to not restore
|
|
||||||
// <https://developer.android.com/reference/android/provider/Settings.Global#STAY_ON_WHILE_PLUGGED_IN>
|
|
||||||
private int restoreStayOn = -1;
|
|
||||||
|
|
||||||
private boolean disableShowTouches;
|
|
||||||
private boolean restoreNormalPowerMode;
|
|
||||||
private boolean powerOffScreen;
|
|
||||||
|
|
||||||
public Config() {
|
|
||||||
// Default constructor, the fields are initialized by CleanUp.configure()
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Config(Parcel in) {
|
|
||||||
displayId = in.readInt();
|
|
||||||
restoreStayOn = in.readInt();
|
|
||||||
byte options = in.readByte();
|
|
||||||
disableShowTouches = (options & FLAG_DISABLE_SHOW_TOUCHES) != 0;
|
|
||||||
restoreNormalPowerMode = (options & FLAG_RESTORE_NORMAL_POWER_MODE) != 0;
|
|
||||||
powerOffScreen = (options & FLAG_POWER_OFF_SCREEN) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeInt(displayId);
|
|
||||||
dest.writeInt(restoreStayOn);
|
|
||||||
byte options = 0;
|
|
||||||
if (disableShowTouches) {
|
|
||||||
options |= FLAG_DISABLE_SHOW_TOUCHES;
|
|
||||||
}
|
|
||||||
if (restoreNormalPowerMode) {
|
|
||||||
options |= FLAG_RESTORE_NORMAL_POWER_MODE;
|
|
||||||
}
|
|
||||||
if (powerOffScreen) {
|
|
||||||
options |= FLAG_POWER_OFF_SCREEN;
|
|
||||||
}
|
|
||||||
dest.writeByte(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasWork() {
|
|
||||||
return disableShowTouches || restoreStayOn != -1 || restoreNormalPowerMode || powerOffScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] serialize() {
|
|
||||||
Parcel parcel = Parcel.obtain();
|
|
||||||
writeToParcel(parcel, 0);
|
|
||||||
byte[] bytes = parcel.marshall();
|
|
||||||
parcel.recycle();
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Config deserialize(byte[] bytes) {
|
|
||||||
Parcel parcel = Parcel.obtain();
|
|
||||||
parcel.unmarshall(bytes, 0, bytes.length);
|
|
||||||
parcel.setDataPosition(0);
|
|
||||||
return CREATOR.createFromParcel(parcel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Config fromBase64(String base64) {
|
|
||||||
byte[] bytes = Base64.decode(base64, Base64.NO_WRAP);
|
|
||||||
return deserialize(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
String toBase64() {
|
|
||||||
byte[] bytes = serialize();
|
|
||||||
return Base64.encodeToString(bytes, Base64.NO_WRAP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CleanUp() {
|
|
||||||
// not instantiable
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void configure(int displayId, int restoreStayOn, boolean disableShowTouches, boolean restoreNormalPowerMode, boolean powerOffScreen)
|
|
||||||
throws IOException {
|
|
||||||
Config config = new Config();
|
|
||||||
config.displayId = displayId;
|
|
||||||
config.disableShowTouches = disableShowTouches;
|
|
||||||
config.restoreStayOn = restoreStayOn;
|
|
||||||
config.restoreNormalPowerMode = restoreNormalPowerMode;
|
|
||||||
config.powerOffScreen = powerOffScreen;
|
|
||||||
|
|
||||||
if (config.hasWork()) {
|
|
||||||
startProcess(config);
|
|
||||||
} else {
|
|
||||||
// There is no additional clean up to do when scrcpy dies
|
|
||||||
unlinkSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void startProcess(Config config) throws IOException {
|
|
||||||
String[] cmd = {"app_process", "/", CleanUp.class.getName(), config.toBase64()};
|
|
||||||
|
|
||||||
ProcessBuilder builder = new ProcessBuilder(cmd);
|
ProcessBuilder builder = new ProcessBuilder(cmd);
|
||||||
builder.environment().put("CLASSPATH", Server.SERVER_PATH);
|
builder.environment().put("CLASSPATH", Server.SERVER_PATH);
|
||||||
builder.start();
|
Process process = builder.start();
|
||||||
|
return new CleanUp(process.getOutputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendMessage(int type, int param) {
|
||||||
|
assert (type & ~MSG_TYPE_MASK) == 0;
|
||||||
|
int msg = type | param << MSG_PARAM_SHIFT;
|
||||||
|
try {
|
||||||
|
out.write(msg);
|
||||||
|
out.flush();
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Ln.w("Could not configure cleanup (type=" + type + ", param=" + param + ")", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setRestoreStayOn(int restoreValue) {
|
||||||
|
// Restore the value (between 0 and 7), -1 to not restore
|
||||||
|
// <https://developer.android.com/reference/android/provider/Settings.Global#STAY_ON_WHILE_PLUGGED_IN>
|
||||||
|
assert restoreValue >= -1 && restoreValue <= 7;
|
||||||
|
return sendMessage(MSG_TYPE_RESTORE_STAY_ON, restoreValue & 0b1111);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setDisableShowTouches(boolean disableOnExit) {
|
||||||
|
return sendMessage(MSG_TYPE_DISABLE_SHOW_TOUCHES, disableOnExit ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setRestoreNormalPowerMode(boolean restoreOnExit) {
|
||||||
|
return sendMessage(MSG_TYPE_RESTORE_NORMAL_POWER_MODE, restoreOnExit ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setPowerOffScreen(boolean powerOffScreenOnExit) {
|
||||||
|
return sendMessage(MSG_TYPE_POWER_OFF_SCREEN, powerOffScreenOnExit ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unlinkSelf() {
|
public static void unlinkSelf() {
|
||||||
@ -148,19 +77,44 @@ public final class CleanUp {
|
|||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
unlinkSelf();
|
unlinkSelf();
|
||||||
|
|
||||||
|
int displayId = Integer.parseInt(args[0]);
|
||||||
|
|
||||||
|
int restoreStayOn = -1;
|
||||||
|
boolean disableShowTouches = false;
|
||||||
|
boolean restoreNormalPowerMode = false;
|
||||||
|
boolean powerOffScreen = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Wait for the server to die
|
// Wait for the server to die
|
||||||
System.in.read();
|
int msg;
|
||||||
|
while ((msg = System.in.read()) != -1) {
|
||||||
|
int type = msg & MSG_TYPE_MASK;
|
||||||
|
int param = msg >> MSG_PARAM_SHIFT;
|
||||||
|
switch (type) {
|
||||||
|
case MSG_TYPE_RESTORE_STAY_ON:
|
||||||
|
restoreStayOn = param > 7 ? -1 : param;
|
||||||
|
break;
|
||||||
|
case MSG_TYPE_DISABLE_SHOW_TOUCHES:
|
||||||
|
disableShowTouches = param != 0;
|
||||||
|
break;
|
||||||
|
case MSG_TYPE_RESTORE_NORMAL_POWER_MODE:
|
||||||
|
restoreNormalPowerMode = param != 0;
|
||||||
|
break;
|
||||||
|
case MSG_TYPE_POWER_OFF_SCREEN:
|
||||||
|
powerOffScreen = param != 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Ln.w("Unexpected msg type: " + type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Expected when the server is dead
|
// Expected when the server is dead
|
||||||
}
|
}
|
||||||
|
|
||||||
Ln.i("Cleaning up");
|
Ln.i("Cleaning up");
|
||||||
|
|
||||||
Config config = Config.fromBase64(args[0]);
|
if (disableShowTouches) {
|
||||||
|
|
||||||
if (config.disableShowTouches || config.restoreStayOn != -1) {
|
|
||||||
if (config.disableShowTouches) {
|
|
||||||
Ln.i("Disabling \"show touches\"");
|
Ln.i("Disabling \"show touches\"");
|
||||||
try {
|
try {
|
||||||
Settings.putValue(Settings.TABLE_SYSTEM, "show_touches", "0");
|
Settings.putValue(Settings.TABLE_SYSTEM, "show_touches", "0");
|
||||||
@ -168,21 +122,21 @@ public final class CleanUp {
|
|||||||
Ln.e("Could not restore \"show_touches\"", e);
|
Ln.e("Could not restore \"show_touches\"", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (config.restoreStayOn != -1) {
|
|
||||||
|
if (restoreStayOn != -1) {
|
||||||
Ln.i("Restoring \"stay awake\"");
|
Ln.i("Restoring \"stay awake\"");
|
||||||
try {
|
try {
|
||||||
Settings.putValue(Settings.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(config.restoreStayOn));
|
Settings.putValue(Settings.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(restoreStayOn));
|
||||||
} catch (SettingsException e) {
|
} catch (SettingsException e) {
|
||||||
Ln.e("Could not restore \"stay_on_while_plugged_in\"", e);
|
Ln.e("Could not restore \"stay_on_while_plugged_in\"", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Device.isScreenOn()) {
|
if (Device.isScreenOn()) {
|
||||||
if (config.powerOffScreen) {
|
if (powerOffScreen) {
|
||||||
Ln.i("Power off screen");
|
Ln.i("Power off screen");
|
||||||
Device.powerOffScreen(config.displayId);
|
Device.powerOffScreen(displayId);
|
||||||
} else if (config.restoreNormalPowerMode) {
|
} else if (restoreNormalPowerMode) {
|
||||||
Ln.i("Restoring normal power mode");
|
Ln.i("Restoring normal power mode");
|
||||||
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
Device.setScreenPowerMode(Device.POWER_MODE_NORMAL);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ public class Controller implements AsyncProcessor {
|
|||||||
|
|
||||||
private final Device device;
|
private final Device device;
|
||||||
private final DesktopConnection connection;
|
private final DesktopConnection connection;
|
||||||
|
private final CleanUp cleanUp;
|
||||||
private final DeviceMessageSender sender;
|
private final DeviceMessageSender sender;
|
||||||
private final boolean clipboardAutosync;
|
private final boolean clipboardAutosync;
|
||||||
private final boolean powerOn;
|
private final boolean powerOn;
|
||||||
@ -41,9 +42,10 @@ public class Controller implements AsyncProcessor {
|
|||||||
|
|
||||||
private boolean keepPowerModeOff;
|
private boolean keepPowerModeOff;
|
||||||
|
|
||||||
public Controller(Device device, DesktopConnection connection, boolean clipboardAutosync, boolean powerOn) {
|
public Controller(Device device, DesktopConnection connection, CleanUp cleanUp, boolean clipboardAutosync, boolean powerOn) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.cleanUp = cleanUp;
|
||||||
this.clipboardAutosync = clipboardAutosync;
|
this.clipboardAutosync = clipboardAutosync;
|
||||||
this.powerOn = powerOn;
|
this.powerOn = powerOn;
|
||||||
initPointers();
|
initPointers();
|
||||||
@ -170,6 +172,10 @@ public class Controller implements AsyncProcessor {
|
|||||||
if (setPowerModeOk) {
|
if (setPowerModeOk) {
|
||||||
keepPowerModeOff = mode == Device.POWER_MODE_OFF;
|
keepPowerModeOff = mode == Device.POWER_MODE_OFF;
|
||||||
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
|
Ln.i("Device screen turned " + (mode == Device.POWER_MODE_OFF ? "off" : "on"));
|
||||||
|
if (cleanUp != null) {
|
||||||
|
boolean mustRestoreOnExit = mode != Device.POWER_MODE_NORMAL;
|
||||||
|
cleanUp.setRestoreNormalPowerMode(mustRestoreOnExit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -51,16 +51,19 @@ public final class Server {
|
|||||||
// not instantiable
|
// not instantiable
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initAndCleanUp(Options options) {
|
private static void initAndCleanUp(Options options, CleanUp cleanUp) {
|
||||||
boolean mustDisableShowTouchesOnCleanUp = false;
|
// This method is called from its own thread, so it may only configure cleanup actions which are NOT dynamic (i.e. they are configured once
|
||||||
int restoreStayOn = -1;
|
// and for all, they cannot be changed from another thread)
|
||||||
boolean restoreNormalPowerMode = options.getControl(); // only restore power mode if control is enabled
|
|
||||||
if (options.getShowTouches() || options.getStayAwake()) {
|
|
||||||
if (options.getShowTouches()) {
|
if (options.getShowTouches()) {
|
||||||
try {
|
try {
|
||||||
String oldValue = Settings.getAndPutValue(Settings.TABLE_SYSTEM, "show_touches", "1");
|
String oldValue = Settings.getAndPutValue(Settings.TABLE_SYSTEM, "show_touches", "1");
|
||||||
// If "show touches" was disabled, it must be disabled back on clean up
|
// If "show touches" was disabled, it must be disabled back on clean up
|
||||||
mustDisableShowTouchesOnCleanUp = !"1".equals(oldValue);
|
if (!"1".equals(oldValue)) {
|
||||||
|
if (!cleanUp.setDisableShowTouches(true)) {
|
||||||
|
Ln.e("Could not disable show touch on exit");
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (SettingsException e) {
|
} catch (SettingsException e) {
|
||||||
Ln.e("Could not change \"show_touches\"", e);
|
Ln.e("Could not change \"show_touches\"", e);
|
||||||
}
|
}
|
||||||
@ -71,26 +74,24 @@ public final class Server {
|
|||||||
try {
|
try {
|
||||||
String oldValue = Settings.getAndPutValue(Settings.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(stayOn));
|
String oldValue = Settings.getAndPutValue(Settings.TABLE_GLOBAL, "stay_on_while_plugged_in", String.valueOf(stayOn));
|
||||||
try {
|
try {
|
||||||
restoreStayOn = Integer.parseInt(oldValue);
|
int restoreStayOn = Integer.parseInt(oldValue);
|
||||||
if (restoreStayOn == stayOn) {
|
if (restoreStayOn != stayOn) {
|
||||||
// No need to restore
|
// Restore only if the current value is different
|
||||||
restoreStayOn = -1;
|
if (!cleanUp.setRestoreStayOn(restoreStayOn)) {
|
||||||
|
Ln.e("Could not restore stay on on exit");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
restoreStayOn = 0;
|
// ignore
|
||||||
}
|
}
|
||||||
} catch (SettingsException e) {
|
} catch (SettingsException e) {
|
||||||
Ln.e("Could not change \"stay_on_while_plugged_in\"", e);
|
Ln.e("Could not change \"stay_on_while_plugged_in\"", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (options.getCleanup()) {
|
if (options.getPowerOffScreenOnClose()) {
|
||||||
try {
|
if (!cleanUp.setPowerOffScreen(true)) {
|
||||||
CleanUp.configure(options.getDisplayId(), restoreStayOn, mustDisableShowTouchesOnCleanUp, restoreNormalPowerMode,
|
Ln.e("Could not power off screen on exit");
|
||||||
options.getPowerOffScreenOnClose());
|
|
||||||
} catch (IOException e) {
|
|
||||||
Ln.e("Could not configure cleanup", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +102,13 @@ public final class Server {
|
|||||||
throw new ConfigurationException("Camera mirroring is not supported");
|
throw new ConfigurationException("Camera mirroring is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread initThread = startInitThread(options);
|
CleanUp cleanUp = null;
|
||||||
|
Thread initThread = null;
|
||||||
|
|
||||||
|
if (options.getCleanup()) {
|
||||||
|
cleanUp = CleanUp.configure(options.getDisplayId());
|
||||||
|
initThread = startInitThread(options, cleanUp);
|
||||||
|
}
|
||||||
|
|
||||||
int scid = options.getScid();
|
int scid = options.getScid();
|
||||||
boolean tunnelForward = options.isTunnelForward();
|
boolean tunnelForward = options.isTunnelForward();
|
||||||
@ -124,7 +131,7 @@ public final class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (control) {
|
if (control) {
|
||||||
Controller controller = new Controller(device, connection, options.getClipboardAutosync(), options.getPowerOn());
|
Controller controller = new Controller(device, connection, cleanUp, options.getClipboardAutosync(), options.getPowerOn());
|
||||||
device.setClipboardListener(text -> controller.getSender().pushClipboardText(text));
|
device.setClipboardListener(text -> controller.getSender().pushClipboardText(text));
|
||||||
asyncProcessors.add(controller);
|
asyncProcessors.add(controller);
|
||||||
}
|
}
|
||||||
@ -167,7 +174,9 @@ public final class Server {
|
|||||||
|
|
||||||
completion.await();
|
completion.await();
|
||||||
} finally {
|
} finally {
|
||||||
|
if (initThread != null) {
|
||||||
initThread.interrupt();
|
initThread.interrupt();
|
||||||
|
}
|
||||||
for (AsyncProcessor asyncProcessor : asyncProcessors) {
|
for (AsyncProcessor asyncProcessor : asyncProcessors) {
|
||||||
asyncProcessor.stop();
|
asyncProcessor.stop();
|
||||||
}
|
}
|
||||||
@ -175,7 +184,9 @@ public final class Server {
|
|||||||
connection.shutdown();
|
connection.shutdown();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (initThread != null) {
|
||||||
initThread.join();
|
initThread.join();
|
||||||
|
}
|
||||||
for (AsyncProcessor asyncProcessor : asyncProcessors) {
|
for (AsyncProcessor asyncProcessor : asyncProcessors) {
|
||||||
asyncProcessor.join();
|
asyncProcessor.join();
|
||||||
}
|
}
|
||||||
@ -187,8 +198,8 @@ public final class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Thread startInitThread(final Options options) {
|
private static Thread startInitThread(final Options options, final CleanUp cleanUp) {
|
||||||
Thread thread = new Thread(() -> initAndCleanUp(options), "init-cleanup");
|
Thread thread = new Thread(() -> initAndCleanUp(options, cleanUp), "init-cleanup");
|
||||||
thread.start();
|
thread.start();
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user