Skip to content

Close the javac pipes and join the drain threads in externalCompile - #110

Merged
pjfanning merged 1 commit into
apache:trunkfrom
pjfanning:leak-codegenutil-process
Sep 7, 2026
Merged

Close the javac pipes and join the drain threads in externalCompile#110
pjfanning merged 1 commit into
apache:trunkfrom
pjfanning:leak-codegenutil-process

Conversation

@pjfanning

Copy link
Copy Markdown
Member

CodeGenUtil.externalCompile never closed any of the three pipes it opens for the compiler process:

  • proc.getOutputStream() (stdin, which javac never reads) is left open;
  • the BufferedReaders wrapping stdout and stderr in copy() are never closed.

That is three file descriptors per invocation, released only when the Process is finally collected.

The drain threads were also never joined. proc.waitFor() returns as soon as the process exits, which can be before the reader threads have finished appending, so the compiler diagnostics printed immediately below could be truncated or empty — the out and err locals were assigned and then never used.

This change closes stdin up front, joins both readers after waitFor(), destroys the process in a finally, and lets copy() close its reader once the pipe is drained.

compile.scomp.checkin.CompilationTests (10 tests, all of which shell out to javac through this path) passes.

🤖 Generated with Claude Code

CodeGenUtil.externalCompile never closed any of the three pipes it opened for
the compiler process. proc.getOutputStream() (stdin, which javac never reads)
was left open, and the BufferedReaders wrapping stdout and stderr in copy()
were never closed, so three file descriptors per invocation were held until
the Process was collected.

The drain threads were also never joined: proc.waitFor() returns as soon as
the process exits, which can be before the readers have finished appending, so
the compiler diagnostics printed just below could be truncated or empty. The
"out" and "err" locals were assigned and then unused.

Close stdin up front, join both readers after waitFor(), destroy the process in
a finally, and let copy() close its reader when the pipe is drained.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pjfanning
pjfanning merged commit 9d12923 into apache:trunk Sep 7, 2026
3 checks passed
@pjfanning
pjfanning deleted the leak-codegenutil-process branch September 7, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant