From c879cb27734473582c43c2d990e8007a8be9bc2f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 06:40:38 +0000 Subject: [PATCH 1/3] Initial plan From b54f3986ddea3877b8277b3434859df1bea4f109 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 06:52:09 +0000 Subject: [PATCH 2/3] Fix Stop Gateway button and settings storage icon warnings - GatewayService.stopGateway(): switch from SIGKILL (destroyForcibly) to SIGTERM (destroy) + 3 s grace period so proot's --kill-on-exit handler can kill its child processes (node.js / openclaw daemon) before proot exits. Fall back to ProcessHandle.descendants() + destroyForcibly if proot does not exit in time. Also interrupt gatewayThread so auto-restart sleep wakes immediately when stopping. Adds descriptive thread name 'gateway-stop'. - SettingsScreen: Storage tile not-granted state now shows green check icon (safe/recommended) instead of amber warning. Updated subtitle to clarify that not granting storage is the recommended state. Agent-Logs-Url: https://github.com/mithun50/openclaw-termux/sessions/9c54b2bb-d170-497f-b4d9-f83b108580bb Co-authored-by: mithun50 <99024517+mithun50@users.noreply.github.com> --- .../com/nxg/openclawproot/GatewayService.kt | 35 +++++++++++++++---- flutter_app/lib/screens/settings_screen.dart | 4 +-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt b/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt index c290859..c632ea2 100644 --- a/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt +++ b/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt @@ -274,6 +274,7 @@ class GatewayService : Service() { } private fun stopGateway() { + val procToStop: Process? synchronized(lock) { stopping = true restartCount = maxRestarts // Prevent auto-restart @@ -281,14 +282,36 @@ class GatewayService : Service() { uptimeThread = null watchdogThread?.interrupt() watchdogThread = null - gatewayProcess?.let { - try { - it.destroyForcibly() - } catch (_: Exception) {} - gatewayProcess = null - } + // Interrupt the gateway thread in case it is sleeping during an + // auto-restart delay so it wakes up and sees stopping=true. + gatewayThread?.interrupt() + gatewayThread = null + procToStop = gatewayProcess + gatewayProcess = null } emitLog("Gateway stopped by user") + // Gracefully terminate proot via SIGTERM first, allowing its --kill-on-exit + // handler to kill child processes (node.js / openclaw daemon) before proot + // exits. destroyForcibly() (SIGKILL) bypasses proot's exit handler, which + // can leave the gateway daemon alive even after proot is killed. + procToStop?.let { proc -> + Thread({ + try { + proc.destroy() // SIGTERM — lets proot clean up its children + if (!proc.waitFor(3, java.util.concurrent.TimeUnit.SECONDS)) { + // proot did not exit in time; force-kill the process tree. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + proc.toHandle().descendants().forEach { it.destroyForcibly() } + } catch (_: Exception) {} + } + proc.destroyForcibly() + } + } catch (_: Exception) { + try { proc.destroyForcibly() } catch (_: Exception) {} + } + }, "gateway-stop").apply { isDaemon = true }.start() + } } /** Watchdog: periodically checks if the proot process is alive. diff --git a/flutter_app/lib/screens/settings_screen.dart b/flutter_app/lib/screens/settings_screen.dart index 3aad664..2c67454 100644 --- a/flutter_app/lib/screens/settings_screen.dart +++ b/flutter_app/lib/screens/settings_screen.dart @@ -120,11 +120,11 @@ class _SettingsScreenState extends State { title: const Text('Setup Storage'), subtitle: Text(_storageGranted ? 'Granted — proot can access /sdcard. Revoke if not needed.' - : 'Allow access to shared storage'), + : 'Not granted (recommended) — tap to grant only if needed'), leading: const Icon(Icons.sd_storage), trailing: _storageGranted ? const Icon(Icons.warning_amber, color: AppColors.statusAmber) - : const Icon(Icons.warning, color: AppColors.statusAmber), + : const Icon(Icons.check_circle, color: AppColors.statusGreen), onTap: () async { await NativeBridge.requestStoragePermission(); // Refresh after returning from permission screen From bd4ef7dcd089256c7be0431ee230ed9b5a55de50 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 08:18:15 +0000 Subject: [PATCH 3/3] Fix compile error: remove Java 9+ Process.toHandle() call incompatible with JVM target 1.8 Agent-Logs-Url: https://github.com/mithun50/openclaw-termux/sessions/3756d90a-f158-4349-b3e6-d5f489dc81e4 Co-authored-by: mithun50 <99024517+mithun50@users.noreply.github.com> --- .../main/kotlin/com/nxg/openclawproot/GatewayService.kt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt b/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt index c632ea2..785ef4a 100644 --- a/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt +++ b/flutter_app/android/app/src/main/kotlin/com/nxg/openclawproot/GatewayService.kt @@ -299,12 +299,7 @@ class GatewayService : Service() { try { proc.destroy() // SIGTERM — lets proot clean up its children if (!proc.waitFor(3, java.util.concurrent.TimeUnit.SECONDS)) { - // proot did not exit in time; force-kill the process tree. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - try { - proc.toHandle().descendants().forEach { it.destroyForcibly() } - } catch (_: Exception) {} - } + // proot did not exit cleanly; force-kill it. proc.destroyForcibly() } } catch (_: Exception) {