mirror of
https://github.com/mihonapp/mihon.git
synced 2026-10-16 13:48:09 -07:00
Fix extension installer crash when cancelling off the main thread
This commit is contained in:
@@ -39,6 +39,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
|
||||
- Fixed refreshing chapters failing with the app language set to Arabic or another language with its own digits ([@AntsyLich](https://github.com/AntsyLich))
|
||||
- Fixed a crash on launch on some Samsung devices running Android 9 to 11 ([@AntsyLich](https://github.com/AntsyLich))
|
||||
- Fixed the start and resume button going under the taskbar on tablets ([@AntsyLich](https://github.com/AntsyLich))
|
||||
- Fixed a crash when updating an extension while others were installing ([@AntsyLich](https://github.com/AntsyLich))
|
||||
|
||||
## [v0.21.0] - 2026-10-12
|
||||
### Added
|
||||
|
||||
@@ -22,6 +22,8 @@ abstract class Installer(private val service: Service) {
|
||||
private val extensionManager: ExtensionManager by lazy { service.appGraph.extensionManager }
|
||||
|
||||
private var waitingInstall = AtomicReference<Entry?>(null)
|
||||
|
||||
// Guarded by itself: cancellation comes from any thread, not only main
|
||||
private val queue = Collections.synchronizedList(mutableListOf<Entry>())
|
||||
|
||||
private val cancelListener: (Long) -> Unit = { downloadId -> cancelQueue(downloadId) }
|
||||
@@ -91,15 +93,15 @@ abstract class Installer(private val service: Service) {
|
||||
if (!ready) {
|
||||
return
|
||||
}
|
||||
if (queue.isEmpty()) {
|
||||
service.stopSelf()
|
||||
return
|
||||
}
|
||||
val nextEntry = queue.first()
|
||||
if (waitingInstall.compareAndSet(null, nextEntry)) {
|
||||
val nextEntry = synchronized(queue) {
|
||||
if (queue.isEmpty()) {
|
||||
service.stopSelf()
|
||||
return
|
||||
}
|
||||
if (!waitingInstall.compareAndSet(null, queue.first())) return
|
||||
queue.removeAt(0)
|
||||
processEntry(nextEntry)
|
||||
}
|
||||
processEntry(nextEntry)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,11 +110,11 @@ abstract class Installer(private val service: Service) {
|
||||
@CallSuper
|
||||
open fun onDestroy() {
|
||||
cancelListeners -= cancelListener
|
||||
queue.forEach {
|
||||
val remaining = synchronized(queue) { queue.toList().also { queue.clear() } }
|
||||
remaining.forEach {
|
||||
logcat(LogPriority.INFO) { "The installer stopped before installing ${it.downloadId}" }
|
||||
extensionManager.updateInstallStep(it.downloadId, InstallStep.Error)
|
||||
}
|
||||
queue.clear()
|
||||
waitingInstall.store(null)
|
||||
}
|
||||
|
||||
@@ -125,7 +127,8 @@ abstract class Installer(private val service: Service) {
|
||||
*/
|
||||
private fun cancelQueue(downloadId: Long) {
|
||||
val waitingInstall = this.waitingInstall.load()
|
||||
val toCancel = queue.find { it.downloadId == downloadId } ?: waitingInstall ?: return
|
||||
val toCancel = synchronized(queue) { queue.find { it.downloadId == downloadId } }
|
||||
?: waitingInstall ?: return
|
||||
if (cancelEntry(toCancel)) {
|
||||
queue.remove(toCancel)
|
||||
if (waitingInstall == toCancel) {
|
||||
|
||||
Reference in New Issue
Block a user