On Windows, every hook run prints a backtrace like this. The hooks themselves work fine, but it's 15-20 lines of stderr per hook file, three times per git commit, which can drown out other overcommit warnings.
<internal:gc>:39: warning: Exception in finalizer #<Tempfile::Remover:0x... @path="C:/Users/.../Temp/out20260914-1480-wyqqru">
c:/Ruby33-x64/lib/ruby/3.3.0/tempfile.rb:319:in `unlink': Permission denied @ apply2files - C:/Users/.../Temp/out20260914-1480-wyqqru (Errno::EACCES)
from c:/Ruby33-x64/lib/ruby/3.3.0/tempfile.rb:319:in `call'
from <internal:gc>:39:in `start'
To reproduce: install hooks and git commit in a repo where a hook's command leaves a process running behind it — bundle exec rspec does, since it's cmd.exe → ruby.exe → ruby.exe. I expected no output here. Overcommit creates these tempfiles and knows when it's done reading them, so deleting them shouldn't be left to GC timing.
What seems to be happening: Subprocess#assign_output_streams makes two Tempfiles for the child's stdout/stderr and never closes them, so Ruby's GC deletes them whenever it gets around to it. By then the leftover grandchild process still has the file open (it inherited the handle), so the delete fails with EACCES and Ruby prints the warning. Closing the streams once wait returns would avoid the whole thing.
Note: it may be better to address this with stream.unlink, rather than File.unlink(stream.path). Tempfile#unlink quietly handles this case and retries later; File.unlink raised an error when I tried it.
Overcommit 0.73.0
Ruby 3.3.6 (x64-mingw-ucrt)
childprocess 5.1.0
git 2.55.0.windows.2
Windows 11
On Windows, every hook run prints a backtrace like this. The hooks themselves work fine, but it's 15-20 lines of stderr per hook file, three times per
git commit, which can drown out other overcommit warnings.To reproduce: install hooks and
git commitin a repo where a hook's command leaves a process running behind it —bundle exec rspecdoes, since it'scmd.exe→ruby.exe→ruby.exe. I expected no output here. Overcommit creates these tempfiles and knows when it's done reading them, so deleting them shouldn't be left to GC timing.What seems to be happening:
Subprocess#assign_output_streamsmakes two Tempfiles for the child's stdout/stderr and never closes them, so Ruby's GC deletes them whenever it gets around to it. By then the leftover grandchild process still has the file open (it inherited the handle), so the delete fails withEACCESand Ruby prints the warning. Closing the streams oncewaitreturns would avoid the whole thing.Note: it may be better to address this with
stream.unlink, rather thanFile.unlink(stream.path).Tempfile#unlinkquietly handles this case and retries later;File.unlinkraised an error when I tried it.Overcommit 0.73.0
Ruby 3.3.6 (x64-mingw-ucrt)
childprocess 5.1.0
git 2.55.0.windows.2
Windows 11