Fix potential thread-safety issue when changing backends

This commit is contained in:
Torsten Grote 2024-10-11 10:36:27 -03:00
parent 3d9eca0d40
commit 2957678465
No known key found for this signature in database
GPG key ID: 3E5F77D92CF891FF
5 changed files with 36 additions and 12 deletions

View file

@ -25,7 +25,10 @@ class BackendManager(
backendFactory: BackendFactory,
) {
@Volatile
private var mBackend: Backend?
@Volatile
private var mBackendProperties: BackendProperties<*>?
val backend: Backend
@ -81,6 +84,8 @@ class BackendManager(
* IMPORTANT: Do no call this while current plugins are being used,
* e.g. while backup/restore operation is still running.
*/
@WorkerThread
@Synchronized
fun <T> changePlugins(
backend: Backend,
storageProperties: BackendProperties<T>,

View file

@ -90,6 +90,7 @@ internal class SafHandler(
return false
}
@WorkerThread
fun setPlugin(safProperties: SafProperties) {
backendManager.changePlugins(
backend = backendFactory.createSafBackend(safProperties),

View file

@ -87,6 +87,7 @@ internal class WebDavHandler(
settingsManager.saveWebDavConfig(properties.config)
}
@WorkerThread
fun setPlugin(properties: WebDavProperties, backend: Backend) {
backendManager.changePlugins(
backend = backend,

View file

@ -7,6 +7,7 @@ package com.stevesoltys.seedvault.repo
import android.content.Context
import android.content.Context.MODE_APPEND
import androidx.annotation.WorkerThread
import com.stevesoltys.seedvault.MemoryLogger
import com.stevesoltys.seedvault.proto.Snapshot
import com.stevesoltys.seedvault.proto.Snapshot.Blob
@ -90,6 +91,7 @@ class BlobCache(
* * changing to a different backup to prevent usage of blobs that don't exist there
* * uploading a new snapshot to prevent the persistent cache from growing indefinitely
*/
@WorkerThread
fun clearLocalCache() {
log.info { "Clearing local cache..." }
context.deleteFile(CACHE_FILE_NAME)

View file

@ -10,6 +10,7 @@ import android.app.backup.IBackupManager
import android.app.job.JobInfo
import android.os.UserHandle
import android.util.Log
import androidx.annotation.UiThread
import androidx.lifecycle.viewModelScope
import androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE
import com.stevesoltys.seedvault.R
@ -23,6 +24,7 @@ import com.stevesoltys.seedvault.worker.AppBackupWorker
import com.stevesoltys.seedvault.worker.BackupRequester.Companion.requestFilesAndAppBackup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.calyxos.backup.storage.api.StorageBackup
import org.calyxos.backup.storage.backup.BackupJobService
import org.calyxos.seedvault.core.backends.Backend
@ -46,25 +48,38 @@ internal class BackupStorageViewModel(
override val isRestoreOperation = false
@UiThread
override fun onSafUriSet(safProperties: SafProperties) {
safHandler.save(safProperties)
safHandler.setPlugin(safProperties)
if (safProperties.isUsb) {
// disable storage backup if new storage is on USB
cancelBackupWorkers()
} else {
// enable it, just in case the previous storage was on USB,
// also to update the network requirement of the new storage
scheduleBackupWorkers()
viewModelScope.launch {
withContext(Dispatchers.IO) {
safHandler.setPlugin(safProperties)
}
withContext(Dispatchers.Main) { // UiThread
if (safProperties.isUsb) {
// disable storage backup if new storage is on USB
cancelBackupWorkers()
} else {
// enable it, just in case the previous storage was on USB,
// also to update the network requirement of the new storage
scheduleBackupWorkers()
}
onStorageLocationSet(safProperties.isUsb)
}
}
onStorageLocationSet(safProperties.isUsb)
}
override fun onWebDavConfigSet(properties: WebDavProperties, backend: Backend) {
webdavHandler.save(properties)
webdavHandler.setPlugin(properties, backend)
scheduleBackupWorkers()
onStorageLocationSet(isUsb = false)
viewModelScope.launch {
withContext(Dispatchers.IO) {
webdavHandler.setPlugin(properties, backend)
}
withContext(Dispatchers.Main) {
scheduleBackupWorkers()
onStorageLocationSet(isUsb = false)
}
}
}
private fun onStorageLocationSet(isUsb: Boolean) {