@@ -20,6 +20,7 @@ import org.getlantern.lantern.BuildConfig
2020import org.getlantern.lantern.MainActivity
2121import org.getlantern.lantern.constant.VPNStatus
2222import org.getlantern.lantern.notification.NotificationHelper
23+ import org.getlantern.lantern.service.LanternVpnService.Companion.ACTION_STOP_VPN
2324import org.getlantern.lantern.utils.AppLogger
2425import org.getlantern.lantern.utils.DeviceUtil
2526import org.getlantern.lantern.utils.FlutterEventListener
@@ -146,8 +147,20 @@ class LanternVpnService :
146147 closeTunInterface()
147148 // Clean up synchronously — cannot use serviceScope here because
148149 // it is cancelled in the finally block below.
149- runCatching { Mobile .stopVPN() }
150- .onFailure { e -> AppLogger .e(TAG , " Mobile.stopVPN() failed during destroy" , e) }
150+ // Only call stopVPN if Radiance IPC is actually running; calling it before
151+ // setup completes results in a misleading "IPC not running" error.
152+ if (Mobile .isRadianceConnected()) {
153+ runCatching { Mobile .stopVPN() }
154+ .onFailure { e ->
155+ AppLogger .e(
156+ TAG ,
157+ " Mobile.stopVPN() failed during destroy" ,
158+ e
159+ )
160+ }
161+ } else {
162+ AppLogger .d(TAG , " Skipping stopVPN — Radiance IPC not running" )
163+ }
151164 runCatching {
152165 runBlocking(Dispatchers .IO ) { DefaultNetworkMonitor .stop() }
153166 }.onFailure { e ->
@@ -263,6 +276,14 @@ class LanternVpnService :
263276 // VPN service starts, replaced by connected notification on success.
264277 notificationHelper.showStartingVPNConnectedNotification(this @LanternVpnService)
265278 runCatching {
279+ // Radiance is pre-warmed via ACTION_START_RADIANCE, but as a background
280+ // service it may have been killed by the OS before setup completed.
281+ // Re-run setup here under the foreground notification so it is guaranteed
282+ // to finish before we attempt to start the VPN tunnel.
283+ if (! Mobile .isRadianceConnected()) {
284+ AppLogger .d(TAG , " Radiance not ready, setting up before VPN start" )
285+ Mobile .setupRadiance(opts(), flutterEventListener)
286+ }
266287 DefaultNetworkMonitor .start()
267288 connect()
268289 VpnStatusManager .postVPNStatus(VPNStatus .Connected )
@@ -296,7 +317,13 @@ class LanternVpnService :
296317 private suspend fun stopVPNTunnel () {
297318 try {
298319 closeTunInterface()
299- runCatching { Mobile .stopVPN() }
320+ runCatching {
321+ if (! Mobile .isVPNConnected()) {
322+ AppLogger .d(TAG , " VPN is not connected, skipping stopVPN" )
323+ return @runCatching
324+ }
325+ Mobile .stopVPN()
326+ }
300327 .onFailure { e -> AppLogger .e(TAG , " Mobile.stopVPN() failed" , e) }
301328
302329 runCatching { DefaultNetworkMonitor .stop() }
0 commit comments