1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-11-26 06:11:19 +00:00

Fix runtime left behind on app update (#31)

* Fix runtime left behind on app update

* Always kill runtime synchronously and run it asynchronously

* More log output
This commit is contained in:
Catfriend1 2018-08-25 21:35:00 +02:00 committed by GitHub
parent bbeecc8777
commit a834edb2bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 23 deletions

View file

@ -169,6 +169,7 @@ public class DrawerFragment extends Fragment implements SyncthingService.OnServi
mActivity.closeDrawer();
break;
case R.id.drawerActionExit:
Log.i(TAG, "Exiting app on user request");
mActivity.stopService(new Intent(mActivity, SyncthingService.class));
mActivity.finish();
mActivity.closeDrawer();

View file

@ -133,10 +133,14 @@ public class SyncthingRunnable implements Runnable {
? pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG)
: null;
try {
if (wakeLock != null)
if (wakeLock != null) {
wakeLock.acquire();
increaseInotifyWatches();
}
/**
* Setup and run a new syncthing instance
*/
increaseInotifyWatches();
HashMap<String, String> targetEnv = buildEnvironment();
process = setupAndLaunch(targetEnv);
@ -216,10 +220,12 @@ public class SyncthingRunnable implements Runnable {
} catch (IOException | InterruptedException e) {
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
} finally {
if (wakeLock != null)
if (wakeLock != null) {
wakeLock.release();
if (process != null)
}
if (process != null) {
process.destroy();
}
}
// Restart syncthing if it exited unexpectedly while running on a separate thread.
@ -346,7 +352,7 @@ public class SyncthingRunnable implements Runnable {
int exitCode;
List<String> syncthingPIDs = getSyncthingPIDs();
if (syncthingPIDs.isEmpty()) {
Log.d(TAG, "killSyncthing: Found no more running instances of " + Constants.FILENAME_SYNCTHING_BINARY);
Log.d(TAG, "killSyncthing: Found no running instances of " + Constants.FILENAME_SYNCTHING_BINARY);
return;
}
for (String syncthingPID : syncthingPIDs) {
@ -358,6 +364,15 @@ public class SyncthingRunnable implements Runnable {
" exit code " + Integer.toString(exitCode));
}
}
/**
* Wait for the syncthing instance to end.
*/
Log.v(TAG, "Waiting for all syncthing instances to end ...");
while (!getSyncthingPIDs().isEmpty()) {
SystemClock.sleep(50);
}
Log.v(TAG, "killSyncthing: Complete.");
}
/**

View file

@ -236,18 +236,19 @@ public class SyncthingService extends Service {
}
if (ACTION_RESTART.equals(intent.getAction()) && mCurrentState == State.ACTIVE) {
shutdown(State.INIT, () -> launchStartupTask());
shutdown(State.INIT, () -> launchStartupTask(SyncthingRunnable.Command.main));
} else if (ACTION_STOP.equals(intent.getAction()) && mCurrentState == State.ACTIVE) {
shutdown(State.DISABLED, () -> {});
} else if (ACTION_RESET_DATABASE.equals(intent.getAction())) {
Log.i(TAG, "Invoking reset of database");
shutdown(State.INIT, () -> {
new SyncthingRunnable(this, SyncthingRunnable.Command.resetdatabase).run();
launchStartupTask();
launchStartupTask(SyncthingRunnable.Command.main);
});
} else if (ACTION_RESET_DELTAS.equals(intent.getAction())) {
Log.i(TAG, "Invoking reset of delta indexes");
shutdown(State.INIT, () -> {
new SyncthingRunnable(this, SyncthingRunnable.Command.resetdeltas).run();
launchStartupTask();
launchStartupTask(SyncthingRunnable.Command.resetdeltas);
});
} else if (ACTION_REFRESH_NETWORK_INFO.equals(intent.getAction())) {
mRunConditionMonitor.updateShouldRunDecision();
@ -282,11 +283,7 @@ public class SyncthingService extends Service {
switch (mCurrentState) {
case DISABLED:
case INIT:
// HACK: Make sure there is no syncthing binary left running from an improper
// shutdown (eg Play Store update).
shutdown(State.INIT, () -> {
launchStartupTask();
});
launchStartupTask(SyncthingRunnable.Command.main);
break;
case STARTING:
case ACTIVE:
@ -309,10 +306,10 @@ public class SyncthingService extends Service {
/**
* Prepares to launch the syncthing binary.
*/
private void launchStartupTask () {
private void launchStartupTask (SyncthingRunnable.Command srCommand) {
Log.v(TAG, "Starting syncthing");
synchronized(mStateLock) {
if (mCurrentState != State.INIT) {
if (mCurrentState != State.DISABLED && mCurrentState != State.INIT) {
Log.e(TAG, "launchStartupTask: Wrong state " + mCurrentState + " detected. Cancelling.");
return;
}
@ -324,7 +321,7 @@ public class SyncthingService extends Service {
return;
}
onServiceStateChange(State.STARTING);
mStartupTask = new StartupTask(this);
mStartupTask = new StartupTask(this, srCommand);
mStartupTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@ -334,9 +331,11 @@ public class SyncthingService extends Service {
*/
private static class StartupTask extends AsyncTask<Void, Void, Void> {
private WeakReference<SyncthingService> refSyncthingService;
private SyncthingRunnable.Command srCommand;
StartupTask(SyncthingService context) {
StartupTask(SyncthingService context, SyncthingRunnable.Command srCommand) {
refSyncthingService = new WeakReference<>(context);
this.srCommand = srCommand;
}
@Override
@ -364,7 +363,7 @@ public class SyncthingService extends Service {
// Get a reference to the service if it is still there.
SyncthingService syncthingService = refSyncthingService.get();
if (syncthingService != null) {
syncthingService.onStartupTaskCompleteListener();
syncthingService.onStartupTaskCompleteListener(srCommand);
}
}
}
@ -372,19 +371,27 @@ public class SyncthingService extends Service {
/**
* Callback on {@link StartupTask#onPostExecute}.
*/
private void onStartupTaskCompleteListener() {
private void onStartupTaskCompleteListener(SyncthingRunnable.Command srCommand) {
if (mApi == null) {
mApi = new RestApi(this, mConfig.getWebGuiUrl(), mConfig.getApiKey(),
this::onApiAvailable, () -> onServiceStateChange(mCurrentState));
Log.i(TAG, "Web GUI will be available at " + mConfig.getWebGuiUrl());
}
// Start the syncthing binary.
// Check mSyncthingRunnable lifecycle and create singleton.
if (mSyncthingRunnable != null || mSyncthingRunnableThread != null) {
Log.e(TAG, "onStartupTaskCompleteListener: Syncthing binary lifecycle violated");
return;
}
mSyncthingRunnable = new SyncthingRunnable(this, SyncthingRunnable.Command.main);
mSyncthingRunnable = new SyncthingRunnable(this, srCommand);
/**
* Check if an old syncthing instance is still running.
* This happens after an in-place app upgrade. If so, end it.
*/
mSyncthingRunnable.killSyncthing();
// Start the syncthing binary in a separate thread.
mSyncthingRunnableThread = new Thread(mSyncthingRunnable);
mSyncthingRunnableThread.start();
@ -643,7 +650,7 @@ public class SyncthingService extends Service {
} catch (IOException e) {
Log.w(TAG, "Failed to import config", e);
}
launchStartupTask();
launchStartupTask(SyncthingRunnable.Command.main);
});
return true;
}