mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-12-23 11:21:29 +00:00
Kill the Syncthing Process before resorting to shell-based kill
Conflicts: src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingRunnable.java
This commit is contained in:
parent
b32ac0b13e
commit
767177e28d
1 changed files with 34 additions and 24 deletions
|
@ -13,6 +13,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the syncthing binary from command line, and prints its output to logcat.
|
* Runs the syncthing binary from command line, and prints its output to logcat.
|
||||||
|
@ -29,11 +30,15 @@ public class SyncthingRunnable implements Runnable {
|
||||||
|
|
||||||
public static final String UNIT_TEST_PATH = "was running";
|
public static final String UNIT_TEST_PATH = "was running";
|
||||||
|
|
||||||
|
private static final AtomicReference<Process> mSyncthing = new AtomicReference<>();
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
private boolean mGenerate;
|
private boolean mGenerate;
|
||||||
|
|
||||||
private String mCommand;
|
private String mSyncthingBinary;
|
||||||
|
|
||||||
|
private String[] mCommand;
|
||||||
|
|
||||||
public enum Command {
|
public enum Command {
|
||||||
generate, // Generate keys, a config file and immediately exit.
|
generate, // Generate keys, a config file and immediately exit.
|
||||||
|
@ -48,16 +53,16 @@ public class SyncthingRunnable implements Runnable {
|
||||||
*/
|
*/
|
||||||
public SyncthingRunnable(Context context, Command command) {
|
public SyncthingRunnable(Context context, Command command) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
String syncthing = mContext.getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME;
|
mSyncthingBinary = mContext.getApplicationInfo().dataDir + "/" + SyncthingService.BINARY_NAME;
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case generate:
|
case generate:
|
||||||
mCommand = syncthing + " -generate='" + mContext.getFilesDir() + "' -no-browser";
|
mCommand = new String[]{ mSyncthingBinary, "-generate", mContext.getFilesDir().toString() };
|
||||||
break;
|
break;
|
||||||
case main:
|
case main:
|
||||||
mCommand = syncthing + " -home='" + mContext.getFilesDir() + "' -no-browser";
|
mCommand = new String[]{ mSyncthingBinary, "-home", mContext.getFilesDir().toString(), "-no-browser" };
|
||||||
break;
|
break;
|
||||||
case reset:
|
case reset:
|
||||||
mCommand = syncthing + " -home='" + mContext.getFilesDir() + "' -reset";
|
mCommand = new String[]{ mSyncthingBinary, "-home", mContext.getFilesDir().toString(), "-reset" };
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.w(TAG, "Unknown command option");
|
Log.w(TAG, "Unknown command option");
|
||||||
|
@ -72,14 +77,21 @@ public class SyncthingRunnable implements Runnable {
|
||||||
*/
|
*/
|
||||||
public SyncthingRunnable(Context context, String manualCommand) {
|
public SyncthingRunnable(Context context, String manualCommand) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mCommand = manualCommand;
|
mCommand = new String[] { manualCommand };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||||
DataOutputStream dos = null;
|
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
// Make sure Syncthing is executable
|
||||||
|
try {
|
||||||
|
ProcessBuilder pb = new ProcessBuilder("chmod", "+x", mSyncthingBinary);
|
||||||
|
pb.start().waitFor();
|
||||||
|
} catch (IOException|InterruptedException e) {
|
||||||
|
Log.w(TAG, "Failed to chmod Syncthing", e);
|
||||||
|
}
|
||||||
|
// Loop Syncthing
|
||||||
Process process = null;
|
Process process = null;
|
||||||
try {
|
try {
|
||||||
// Loop to handle Syncthing restarts (these always have an error code of 3).
|
// Loop to handle Syncthing restarts (these always have an error code of 3).
|
||||||
|
@ -94,16 +106,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
env.put("STGUIAUTH", sp.getString("gui_user", "") + ":" +
|
env.put("STGUIAUTH", sp.getString("gui_user", "") + ":" +
|
||||||
sp.getString("gui_password", ""));
|
sp.getString("gui_password", ""));
|
||||||
process = pb.start();
|
process = pb.start();
|
||||||
|
mSyncthing.set(process);
|
||||||
dos = new DataOutputStream(process.getOutputStream());
|
|
||||||
// Set (Android) home directory to data folder for syncthing to use.
|
|
||||||
dos.writeBytes("HOME=" + Environment.getExternalStorageDirectory() + " ");
|
|
||||||
dos.writeBytes("STTRACE=" + pm.getString("sttrace", "") + " ");
|
|
||||||
dos.writeBytes("STNORESTART=1 ");
|
|
||||||
dos.writeBytes("STNOUPGRADE=1 ");
|
|
||||||
dos.writeBytes(mCommand);
|
|
||||||
dos.writeBytes("\nexit\n");
|
|
||||||
dos.flush();
|
|
||||||
|
|
||||||
log(process.getInputStream(), Log.INFO);
|
log(process.getInputStream(), Log.INFO);
|
||||||
log(process.getErrorStream(), Log.WARN);
|
log(process.getErrorStream(), Log.WARN);
|
||||||
|
@ -111,6 +114,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
niceSyncthing();
|
niceSyncthing();
|
||||||
|
|
||||||
ret = process.waitFor();
|
ret = process.waitFor();
|
||||||
|
mSyncthing.set(null);
|
||||||
|
|
||||||
if (ret == 3) {
|
if (ret == 3) {
|
||||||
Log.i(TAG, "Restarting syncthing");
|
Log.i(TAG, "Restarting syncthing");
|
||||||
|
@ -121,12 +125,6 @@ public class SyncthingRunnable implements Runnable {
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
|
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
|
||||||
if (dos != null)
|
|
||||||
dos.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, "Failed to close shell stream", e);
|
|
||||||
}
|
|
||||||
if (process != null)
|
if (process != null)
|
||||||
process.destroy();
|
process.destroy();
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
|
@ -149,7 +147,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
Thread.sleep(1000); // Wait a second before getting the pid
|
Thread.sleep(1000); // Wait a second before getting the pid
|
||||||
nice = Runtime.getRuntime().exec("sh");
|
nice = Runtime.getRuntime().exec("sh");
|
||||||
niceOut = new DataOutputStream(nice.getOutputStream());
|
niceOut = new DataOutputStream(nice.getOutputStream());
|
||||||
niceOut.writeBytes("set `ps |grep libsyncthing.so`\n");
|
niceOut.writeBytes("set `ps | grep libsyncthing.so`\n");
|
||||||
niceOut.writeBytes("ionice $2 be 7\n"); // best-effort, low priority
|
niceOut.writeBytes("ionice $2 be 7\n"); // best-effort, low priority
|
||||||
niceOut.writeBytes("exit\n");
|
niceOut.writeBytes("exit\n");
|
||||||
log(nice.getErrorStream(), Log.WARN);
|
log(nice.getErrorStream(), Log.WARN);
|
||||||
|
@ -183,6 +181,18 @@ public class SyncthingRunnable implements Runnable {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static void killSyncthing() {
|
public static void killSyncthing() {
|
||||||
|
final Process p = mSyncthing.get();
|
||||||
|
if (p != null) {
|
||||||
|
mSyncthing.set(null);
|
||||||
|
p.destroy();
|
||||||
|
try {
|
||||||
|
p.waitFor();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.w(TAG_KILL, "Failed to kill Syncthing's process", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure kill
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
Process ps = null;
|
Process ps = null;
|
||||||
DataOutputStream psOut = null;
|
DataOutputStream psOut = null;
|
||||||
|
|
Loading…
Reference in a new issue