Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d75e9c9 authored by Adrian Roos's avatar Adrian Roos
Browse files

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
parent e8fd15b2
Loading
Loading
Loading
Loading
+46 −42
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ object ProtoLogTool {


        val executor = newThreadPool()
        val executor = newThreadPool()


        try {
            command.javaSourceArgs.map { path ->
            command.javaSourceArgs.map { path ->
                executor.submitCallable {
                executor.submitCallable {
                    val transformer = SourceTransformer(command.protoLogImplClassNameArg,
                    val transformer = SourceTransformer(command.protoLogImplClassNameArg,
@@ -67,8 +68,8 @@ object ProtoLogTool {
                            text
                            text
                        }
                        }
                    } catch (ex: ParsingException) {
                    } catch (ex: ParsingException) {
                    // If we cannot parse this file, skip it (and log why). Compilation will fail
                        // If we cannot parse this file, skip it (and log why). Compilation will
                    // in a subsequent build step.
                        // fail in a subsequent build step.
                        injector.reportParseError(ex)
                        injector.reportParseError(ex)
                        text
                        text
                    }
                    }
@@ -80,8 +81,9 @@ object ProtoLogTool {
                outJar.write(outSrc.toByteArray())
                outJar.write(outSrc.toByteArray())
                outJar.closeEntry()
                outJar.closeEntry()
            }
            }

        } finally {
            executor.shutdown()
            executor.shutdown()
        }


        val cacheSplit = command.protoLogCacheClassNameArg.split(".")
        val cacheSplit = command.protoLogCacheClassNameArg.split(".")
        val cacheName = cacheSplit.last()
        val cacheName = cacheSplit.last()
@@ -153,6 +155,7 @@ ${updates.replaceIndent(" ")}


        val executor = newThreadPool()
        val executor = newThreadPool()


        try {
            command.javaSourceArgs.map { path ->
            command.javaSourceArgs.map { path ->
                executor.submitCallable {
                executor.submitCallable {
                    val file = File(path)
                    val file = File(path)
@@ -162,8 +165,8 @@ ${updates.replaceIndent(" ")}
                            val code = tryParse(text, path)
                            val code = tryParse(text, path)
                            builder.findLogCalls(code, path, packagePath(file, code))
                            builder.findLogCalls(code, path, packagePath(file, code))
                        } catch (ex: ParsingException) {
                        } catch (ex: ParsingException) {
                        // If we cannot parse this file, skip it (and log why). Compilation will fail
                            // If we cannot parse this file, skip it (and log why). Compilation will
                        // in a subsequent build step.
                            // fail in a subsequent build step.
                            injector.reportParseError(ex)
                            injector.reportParseError(ex)
                            null
                            null
                        }
                        }
@@ -174,8 +177,9 @@ ${updates.replaceIndent(" ")}
            }.forEach { future ->
            }.forEach { future ->
                builder.addLogCalls(future.get() ?: return@forEach)
                builder.addLogCalls(future.get() ?: return@forEach)
            }
            }

        } finally {
            executor.shutdown()
            executor.shutdown()
        }


        val out = injector.fileOutputStream(command.viewerConfigJsonArg)
        val out = injector.fileOutputStream(command.viewerConfigJsonArg)
        out.write(builder.build().toByteArray())
        out.write(builder.build().toByteArray())