@@ -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