Skip to content

Commit 9fccbf4

Browse files
Added support for collecting thread dumps for IBM8 Java (#10646)
Added support for taking thread dumps for IBM8 Java. Code cleanup. Minor. Cleanup. Co-authored-by: alexey.kuznetsov <alexey.kuznetsov@datadoghq.com>
1 parent e9b5a57 commit 9fccbf4

1 file changed

Lines changed: 43 additions & 16 deletions

File tree

buildSrc/src/main/kotlin/datadog/gradle/plugin/dump/DumpHangedTestPlugin.kt

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -123,30 +123,37 @@ class DumpHangedTestPlugin : Plugin<Project> {
123123
fun file(name: String, ext: String = "log") =
124124
File(dumpsDir, "$name-${System.currentTimeMillis()}.$ext")
125125

126-
// For simplicity, use `0` as the PID, which collects all thread dumps across JVMs.
127-
val allThreadsFile = file("all-thread-dumps")
128-
runCmd(Redirect.to(allThreadsFile), "jcmd", "0", "Thread.print", "-l")
129-
130126
// Collect all JVMs pids.
131127
val allJavaProcessesFile = file("all-java-processes")
132128
runCmd(Redirect.to(allJavaProcessesFile), "jcmd", "-l")
133129

134-
// Collect pids for 'Gradle Test Executor'.
135-
val pids = allJavaProcessesFile.readLines()
136-
.filter { it.contains("Gradle Test Executor") }
137-
.map { it.substringBefore(' ') }
130+
// On IBM JDK thread dump can be collected by signaling the matching `Gradle Test Executor` process with `kill -3`.
131+
// It will be writen into `/tmp/javacore.YYYYMMDD.HHMMSS.PID.SEQ.txt
132+
if (isIbm8(allJavaProcessesFile)) {
133+
val allProcessesFile = file("all-processes")
134+
runCmd(Redirect.to(allProcessesFile), "ps", "-ef")
135+
extractPidsIbm8(allProcessesFile).forEach { ibm8Pid ->
136+
runCmd(Redirect.INHERIT, "kill", "-3", ibm8Pid)
137+
}
138+
} else {
139+
val pids = extractPids(allJavaProcessesFile)
138140

139-
pids.forEach { pid ->
140-
// Collect heap dump by pid.
141-
val heapDumpPath = file("${pid}-heap-dump", "hprof").absolutePath
142-
runCmd(Redirect.INHERIT, "jcmd", pid, "GC.heap_dump", heapDumpPath)
141+
pids.forEach { pid ->
142+
// Collect heap dump by pid.
143+
val heapDumpPath = file("${pid}-heap-dump", "hprof").absolutePath
144+
runCmd(Redirect.INHERIT, "jcmd", pid, "GC.heap_dump", heapDumpPath)
143145

144-
// Collect thread dump by pid.
145-
val threadDumpFile = file("${pid}-thread-dump")
146-
runCmd(Redirect.to(threadDumpFile), "jcmd", pid, "Thread.print", "-l")
146+
// Collect thread dump by pid.
147+
val threadDumpFile = file("${pid}-thread-dump")
148+
runCmd(Redirect.to(threadDumpFile), "jcmd", pid, "Thread.print", "-l")
149+
}
150+
151+
// Just in case collect all thread dumps by using special PID `0`.
152+
val allThreadsFile = file("all-thread-dumps")
153+
runCmd(Redirect.to(allThreadsFile), "jcmd", "0", "Thread.print", "-l")
147154
}
148155
} catch (e: Throwable) {
149-
t.logger.warn("Taking dumps failed with error: ${e.message}, for ${t.path}")
156+
t.logger.warn("Taking dumps failed with error: ${e.message ?: e.javaClass.name}, for ${t.path}")
150157
}
151158
}
152159

@@ -175,4 +182,24 @@ class DumpHangedTestPlugin : Plugin<Project> {
175182
throw IOException("Process failed: ${args.joinToString(" ")}, exit code: $exitCode")
176183
}
177184
}
185+
186+
private fun isIbm8(file: File): Boolean =
187+
file.readLines().any { it.contains("-PtestJvm=ibm8") }
188+
189+
private fun extractPids(file: File): List<String> =
190+
file.readLines()
191+
.filter { it.contains("Gradle Test Executor") }
192+
.map { it.substringBefore(' ') }
193+
194+
private fun extractPidsIbm8(file: File): List<String> =
195+
file.readLines()
196+
.filter { it.contains("Gradle Test Executor") }
197+
.filter { it.contains("ibm", ignoreCase = true) }
198+
.mapNotNull(::extractPid)
199+
200+
private val whitespaceRegex = Regex("\\s+")
201+
202+
// ps -ef format produce output like: UID PID PPID ...
203+
private fun extractPid(line: String): String? =
204+
line.trimStart().split(whitespaceRegex, limit = 3).getOrNull(1)
178205
}

0 commit comments

Comments
 (0)