Skip to content

Commit

Permalink
Fixed killing jcef processes
Browse files Browse the repository at this point in the history
  • Loading branch information
smilefx committed Nov 13, 2024
1 parent d4c354c commit 81740e0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import InternalCameraPaneData
import data.event.*
import data.event.internal.*
import jsonMapper
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.serialization.ExperimentalSerializationApi
import mapper.DialogMapper
import me.friwi.jcefmaven.CefAppBuilder
Expand Down Expand Up @@ -45,10 +49,15 @@ import java.awt.EventQueue
import java.awt.KeyboardFocusManager
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import java.io.File
import java.lang.management.ManagementFactory
import java.net.ServerSocket
import java.util.stream.Collectors
import java.util.stream.Stream
import javax.imageio.ImageIO
import javax.swing.JFrame
import javax.swing.WindowConstants.EXIT_ON_CLOSE
import kotlin.concurrent.timer
import kotlin.system.exitProcess


Expand Down Expand Up @@ -192,7 +201,7 @@ class JCEFApplication : Application {

}

@OptIn(ExperimentalSerializationApi::class)
@OptIn(ExperimentalSerializationApi::class, DelicateCoroutinesApi::class)
class MainFrame(
startURL: String = "http://localhost",
useOSR: Boolean = false,
Expand Down Expand Up @@ -227,7 +236,8 @@ class MainFrame(
})

val cefApp = builder.build()

val pids = mutableSetOf<Long>()
var pidsUnchanged = 0

val platform = EnumPlatform.getCurrentPlatform()
println(platform)
Expand Down Expand Up @@ -330,10 +340,47 @@ class MainFrame(

override fun windowOpened(e: WindowEvent?) {
super.windowOpened(e)

println("Application is running with PID: ${ManagementFactory.getRuntimeMXBean().name}")
timer(period = 1000) {
val pidsBefore = pids.size
pids += filterJCEFHelperProcesses(getChildProcessIds())
if(pids.size == pidsBefore) {
pidsUnchanged++
} else {
pidsUnchanged = 0
}

if(pidsUnchanged >= 2) {
println("JCEF Helper PIDs: $pids")
File("build/application.pid").writeText(pids.joinToString(",").trim())
this.cancel()
}
}
}
})
}

internal fun getChildProcessIds(process: ProcessHandle = ProcessHandle.current()): Set<Long> {
val childrenList = mutableListOf<ProcessHandle>()
val children = process.children().let {
it.forEach { childrenList.add(it) }
childrenList
}
return (children.flatMap { getChildProcessIds(it) } + children.map { it.pid() }).toSet()
}

internal fun getChildrenJCEFHelperProcesses(): Set<Long> {
return ProcessHandle.allProcesses()
.filter { it.info().command().orElse("").contains("jcef_helper") }
.map { it.pid() }
.collect(Collectors.toSet())
}

internal fun filterJCEFHelperProcesses(pids: Set<Long>): Set<Long> {
return pids.filter { it in getChildrenJCEFHelperProcesses() }.toSet()
}

fun setDialogContent(browser : CefBrowser, dialogData : DialogData) {
browser.executeJavaScript(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,83 +163,27 @@ tasks.named<Copy>("jvmProcessResources") {
from(jsBrowserDistribution)
}

var initialHelperPIDs = setOf<Long>()

// Cleanup task that depends on tracking `jcef_helper.exe` processes
val cleanupJcefHelper by
tasks.registering {
group = "application"
description = "Cleans up orphaned jcef_helper processes after the run task"

doLast {
// After 'run' completes, find new `jcef_helper.exe` processes and terminate them
println("Initial jcef_helper PIDs: $initialHelperPIDs")
val currentHelperPIDs = getCurrentJcefHelperPIDs()
println("Current jcef_helper PIDs: $currentHelperPIDs")
val newHelperPIDs = currentHelperPIDs - initialHelperPIDs
println("New jcef_helper PIDs: $newHelperPIDs")

println(newHelperPIDs.map {
getParentProcessId(it)
})

// Kill only new helper processes started during the run
killJcefHelperProcesses(newHelperPIDs)
}
}

tasks.named<JavaExec>("run") {
doFirst {
initialHelperPIDs = getCurrentJcefHelperPIDs()
println("Initial jcef_helper PIDs: $initialHelperPIDs")
}

dependsOn(tasks.named<Jar>("jvmJar"))
classpath(tasks.named<Jar>("jvmJar"))

doLast {
val currentHelperPIDs = getCurrentJcefHelperPIDs()
println("After jcef_helper PIDs: $currentHelperPIDs")
println(currentHelperPIDs.map {
getParentProcessId(it)
})
}
}

// TODO - Somehow invoke this function from implementations of dependency
gradle.buildFinished {
println("Build finished, cleaning up jcef_helper processes")
tasks.named("cleanupJcefHelper").get().actions.forEach {
it.execute(tasks.named("cleanupJcefHelper").get())
}
}

// Helper function to get current jcef_helper process IDs
fun getCurrentJcefHelperPIDs(): Set<Long> {
return ProcessHandle.allProcesses()
.filter { it.info().command().orElse("").contains("jcef_helper") }
.map { it.pid() }
.collect(Collectors.toSet())
}

// Function to get the parent process ID of a given process
fun getParentProcessId(pid: Long): Long? {
val osBean = ManagementFactory.getOperatingSystemMXBean() as OperatingSystemMXBean
val processHandle = ProcessHandle.of(pid)
return processHandle.orElse(null)?.parent()?.orElse(null)?.pid()
try {
val applicationPIDs = file("build/application.pid").readText().split(",").map { it.toLong() }.toSet()
println("Created JCEF_Helper PIDs: $applicationPIDs")
killJcefHelperProcesses(applicationPIDs)
} catch (e: Exception) {}
}

// Function to kill JCEF helper processes
fun killJcefHelperProcesses(pids: Set<Long>) {
val currentProcessId = ProcessHandle.current().pid()
pids.forEach { pid ->
val parentPid = getParentProcessId(pid)
println("Parent process ID of $pid is $parentPid")
if (parentPid == currentProcessId) {
println("Killing process $pid which is a child of the current process $currentProcessId")
Runtime.getRuntime().exec("kill -9 $pid")
} else {
println("Skipping process $pid as it is not a child of the current process $currentProcessId")
}
ProcessHandle.of(pid).ifPresent {
println("Killing process $pid")
it.destroy()
}
}
}

Expand Down

0 comments on commit 81740e0

Please sign in to comment.