diff options
Diffstat (limited to 'app/src/main/java')
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/RsyncRunner.kt | 20 | ||||
| -rw-r--r-- | app/src/main/java/invalid/lena/rsend/SyncWorker.kt | 3 |
2 files changed, 19 insertions, 4 deletions
diff --git a/app/src/main/java/invalid/lena/rsend/RsyncRunner.kt b/app/src/main/java/invalid/lena/rsend/RsyncRunner.kt index d8f8b93..c37e3ce 100644 --- a/app/src/main/java/invalid/lena/rsend/RsyncRunner.kt +++ b/app/src/main/java/invalid/lena/rsend/RsyncRunner.kt @@ -1,6 +1,9 @@ package invalid.lena.rsend import android.content.Context +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch // RsyncRunner builds and runs the rsync invocation for one folder, streaming // rsync's output into the log. It uses the bundled rsync and rsh binaries and @@ -34,14 +37,23 @@ object RsyncRunner { private fun withSlash(p: String): String = if (p.endsWith("/")) p else "$p/" // runFolder execs rsync for one folder, appending every output line to the - // log, and returns rsync's exit code. - fun runFolder(ctx: Context, remote: Remote, f: Folder, log: SyncLog): Int { + // log, and returns rsync's exit code. Blocks the calling thread (run it on + // an IO dispatcher). If the caller is cancelled (worker stopped, schedule + // replaced, constraints lost) the watchdog kills rsync rather than leave it + // running detached; killing it also closes its pipes, which unblocks the + // log reader below. destroy() on an already-exited process is a no-op. + suspend fun runFolder(ctx: Context, remote: Remote, f: Folder, log: SyncLog): Int = coroutineScope { val cmd = listOf(Native.rsync(ctx).absolutePath) + args(Native.rsh(ctx).absolutePath, remote, f) log.line("rsync ${cmd.drop(1).joinToString(" ")}") val pb = ProcessBuilder(cmd).redirectErrorStream(true) pb.environment().putAll(Keys.env(ctx, remote.port)) val p = pb.start() - p.inputStream.bufferedReader().forEachLine { log.line(it) } - return p.waitFor() + val watchdog = launch { try { awaitCancellation() } finally { p.destroy() } } + try { + p.inputStream.bufferedReader().forEachLine { log.line(it) } + p.waitFor() + } finally { + watchdog.cancel() + } } } diff --git a/app/src/main/java/invalid/lena/rsend/SyncWorker.kt b/app/src/main/java/invalid/lena/rsend/SyncWorker.kt index a70a3e6..1b14673 100644 --- a/app/src/main/java/invalid/lena/rsend/SyncWorker.kt +++ b/app/src/main/java/invalid/lena/rsend/SyncWorker.kt @@ -61,6 +61,9 @@ class SyncWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, 1 } else try { RsyncRunner.runFolder(ctx, cfg.remote, f, log) + } catch (e: CancellationException) { + log.line("cancelled") + throw e } catch (e: Exception) { log.line("error: ${e.message}") 1 |