diff options
author | Adrian Roos <roosa@google.com> | 2020-01-10 19:24:03 +0100 |
---|---|---|
committer | Adrian Roos <roosa@google.com> | 2020-01-16 19:13:13 +0000 |
commit | 1d75e9c921e91b0800998995c734cc2211d4fdb8 (patch) | |
tree | c8abed37920a441ce865237c129077917e1af6f7 /tools/protologtool | |
parent | e8fd15b2cc271502e189c767bbb50febced5e8ec (diff) |
ProtoLogTool: Fix thread pool leak on code generation exception
Fixes an issue where the thread pool leaks when code generation
throws an exception (for example because of an invalid log string).
When the thread pool leaks, System.exit() no longer works, because
the JVM waits for all threads to exit - which never happens for the
leaked thread pool.
Test: `ProtoLog.w(LOG_GROUP, new String())` -> make droid should not hang
Change-Id: Ibdae0f1e68441c6fe004398d146f496503ccc4cd
Diffstat (limited to 'tools/protologtool')
-rw-r--r-- | tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt | 88 |
1 files changed, 46 insertions, 42 deletions
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt index 99a26dc80288..3c55237ce443 100644 --- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt +++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt @@ -53,36 +53,38 @@ object ProtoLogTool { val executor = newThreadPool() - command.javaSourceArgs.map { path -> - executor.submitCallable { - val transformer = SourceTransformer(command.protoLogImplClassNameArg, - command.protoLogCacheClassNameArg, processor) - val file = File(path) - val text = injector.readText(file) - val outSrc = try { - val code = tryParse(text, path) - if (containsProtoLogText(text, command.protoLogClassNameArg)) { - transformer.processClass(text, path, packagePath(file, code), code) - } else { + try { + command.javaSourceArgs.map { path -> + executor.submitCallable { + val transformer = SourceTransformer(command.protoLogImplClassNameArg, + command.protoLogCacheClassNameArg, processor) + val file = File(path) + val text = injector.readText(file) + val outSrc = try { + val code = tryParse(text, path) + if (containsProtoLogText(text, command.protoLogClassNameArg)) { + transformer.processClass(text, path, packagePath(file, code), code) + } else { + text + } + } catch (ex: ParsingException) { + // If we cannot parse this file, skip it (and log why). Compilation will + // fail in a subsequent build step. + injector.reportParseError(ex) text } - } catch (ex: ParsingException) { - // If we cannot parse this file, skip it (and log why). Compilation will fail - // in a subsequent build step. - injector.reportParseError(ex) - text + path to outSrc } - path to outSrc + }.map { future -> + val (path, outSrc) = future.get() + outJar.putNextEntry(ZipEntry(path)) + outJar.write(outSrc.toByteArray()) + outJar.closeEntry() } - }.map { future -> - val (path, outSrc) = future.get() - outJar.putNextEntry(ZipEntry(path)) - outJar.write(outSrc.toByteArray()) - outJar.closeEntry() + } finally { + executor.shutdown() } - executor.shutdown() - val cacheSplit = command.protoLogCacheClassNameArg.split(".") val cacheName = cacheSplit.last() val cachePackage = cacheSplit.dropLast(1).joinToString(".") @@ -153,30 +155,32 @@ ${updates.replaceIndent(" ")} val executor = newThreadPool() - command.javaSourceArgs.map { path -> - executor.submitCallable { - val file = File(path) - val text = injector.readText(file) - if (containsProtoLogText(text, command.protoLogClassNameArg)) { - try { - val code = tryParse(text, path) - builder.findLogCalls(code, path, packagePath(file, code)) - } catch (ex: ParsingException) { - // If we cannot parse this file, skip it (and log why). Compilation will fail - // in a subsequent build step. - injector.reportParseError(ex) + try { + command.javaSourceArgs.map { path -> + executor.submitCallable { + val file = File(path) + val text = injector.readText(file) + if (containsProtoLogText(text, command.protoLogClassNameArg)) { + try { + val code = tryParse(text, path) + builder.findLogCalls(code, path, packagePath(file, code)) + } catch (ex: ParsingException) { + // If we cannot parse this file, skip it (and log why). Compilation will + // fail in a subsequent build step. + injector.reportParseError(ex) + null + } + } else { null } - } else { - null } + }.forEach { future -> + builder.addLogCalls(future.get() ?: return@forEach) } - }.forEach { future -> - builder.addLogCalls(future.get() ?: return@forEach) + } finally { + executor.shutdown() } - executor.shutdown() - val out = injector.fileOutputStream(command.viewerConfigJsonArg) out.write(builder.build().toByteArray()) out.close() |