Skip to content

Commit 23e473a

Browse files
YangQi0408pomelohan
authored andcommitted
manager: fix TransactionTooLargeException crash on large module install logs
When installing modules that produce large log output (e.g. theme modules with thousands of icons), the install log text state grows unboundedly, causing TransactionTooLargeException when the Activity's saved state Bundle exceeds the Binder transaction limit (~1MB). This was previously reported in #927 and fixed in cb684e6 by switching from rememberSaveable to remember, but that caused the log to reset on navigation (#1308). Fix both issues by: - Using rememberSaveable for text state (preserves log on navigation) - Truncating text at runtime to 100K chars when it exceeds the limit - Keeping full log in StringBuilder (remember) for saving to file - Also fixing ExecuteAPMActionScreen which had the same issue The 100K char limit (~100KB) is well below the Binder limit and still covers ~2000-3000 lines of install log output. Closes: #927
1 parent 4c113e9 commit 23e473a

2 files changed

Lines changed: 25 additions & 20 deletions

File tree

app/src/main/java/me/bmax/apatch/ui/screen/ExecuteAPMAction.kt

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable
2121
import androidx.compose.runtime.LaunchedEffect
2222
import androidx.compose.runtime.getValue
2323
import androidx.compose.runtime.mutableStateOf
24+
import androidx.compose.runtime.remember
2425
import androidx.compose.runtime.rememberCoroutineScope
2526
import androidx.compose.runtime.saveable.rememberSaveable
2627
import androidx.compose.runtime.setValue
@@ -50,13 +51,18 @@ import java.util.Locale
5051
@Destination<RootGraph>
5152
fun ExecuteAPMActionScreen(navigator: DestinationsNavigator, moduleId: String) {
5253
var text by rememberSaveable { mutableStateOf("") }
53-
var tempText: String
54-
val logContent = rememberSaveable { StringBuilder() }
54+
val logContent = remember { StringBuilder() }
5555
val snackBarHost = LocalSnackbarHost.current
5656
val scope = rememberCoroutineScope()
5757
val scrollState = rememberScrollState()
5858
var actionResult: Boolean
5959

60+
fun appendLog(line: String) {
61+
logContent.append(line).append("\n")
62+
val newText = text + line + "\n"
63+
text = if (newText.length > 100_000) newText.takeLast(100_000) else newText
64+
}
65+
6066
LaunchedEffect(Unit) {
6167
if (text.isNotEmpty()) {
6268
return@LaunchedEffect
@@ -65,16 +71,14 @@ fun ExecuteAPMActionScreen(navigator: DestinationsNavigator, moduleId: String) {
6571
runAPModuleAction(
6672
moduleId,
6773
onStdout = {
68-
tempText = "$it\n"
69-
if (tempText.startsWith("")) { // clear command
70-
text = tempText.substring(6)
74+
if (it.startsWith("\u001B[H\u001B[2J")) { // clear command
75+
text = it.substring(9)
7176
} else {
72-
text += tempText
77+
appendLog(it)
7378
}
74-
logContent.append(it).append("\n")
7579
},
7680
onStderr = {
77-
logContent.append(it).append("\n")
81+
appendLog(it)
7882
}
7983
).let {
8084
actionResult = it

app/src/main/java/me/bmax/apatch/ui/screen/Install.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,15 @@ enum class MODULE_TYPE {
7676
@Composable
7777
@Destination<RootGraph>
7878
fun InstallScreen(navigator: DestinationsNavigator, uri: Uri, type: MODULE_TYPE) {
79-
var text by remember { mutableStateOf("") }
80-
var tempText: String
79+
var text by rememberSaveable { mutableStateOf("") }
8180
val logContent = remember { StringBuilder() }
8281
var showFloatAction by rememberSaveable { mutableStateOf(false) }
82+
83+
fun appendLog(line: String) {
84+
logContent.append(line).append("\n")
85+
val newText = text + line + "\n"
86+
text = if (newText.length > 100_000) newText.takeLast(100_000) else newText
87+
}
8388
val metaModuleAlertDialog = rememberCustomDialog { dismiss: () -> Unit ->
8489
val uriHandler = LocalUriHandler.current
8590
AlertDialog(
@@ -141,21 +146,17 @@ fun InstallScreen(navigator: DestinationsNavigator, uri: Uri, type: MODULE_TYPE)
141146
}
142147

143148
}, onStdout = {
144-
tempText = "$it\n"
145-
if (tempText.startsWith("")) { // clear command
146-
text = tempText.substring(6)
149+
if (it.startsWith("[H[J")) { // clear command
150+
text = it.substring(5)
147151
} else {
148-
text += tempText
152+
appendLog(it)
149153
}
150-
logContent.append(it).append("\n")
151154
}, onStderr = {
152-
tempText = "$it\n"
153-
if (tempText.startsWith("")) { // clear command
154-
text = tempText.substring(6)
155+
if (it.startsWith("[H[J")) { // clear command
156+
text = it.substring(5)
155157
} else {
156-
text += tempText
158+
appendLog(it)
157159
}
158-
logContent.append(it).append("\n")
159160
})
160161
}
161162
}

0 commit comments

Comments
 (0)