Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed: SymWriter COM object is not released on exception #955

Merged

Conversation

OskiKervinen-MF
Copy link
Contributor

@OskiKervinen-MF OskiKervinen-MF commented Jul 19, 2024

The Problem

Accessing a PDB file edited with Cecil randomly produces errors about the file being locked.
Problem observed when being used in coverlet:
coverlet-coverage/coverlet#1471

This is caused by an exclusive file handle held by the SymWriter COM object.
It is not released before the COM object is released.
In normal execution, NativePdbWriter.Write calls SymWriter.Close at the end,
which in turn calls Marshal.ReleaseComObject, releasing the object and file handle.
But if an exception causes NativePdbWriter.Write to never be called, there is no call to SymWriter.Close,
which in turn means Marshal.ReleaseComObject is left uncalled.

The garbage collector will eventually destroy the object and thereby release the COM object, but that happens non-deterministically. The result was random file access issues with the PDB file.

The Solution

Luckily NativePdbWriter is IDisposable. I added a call to writer.Close to the Dispose. But now Close could be called twice, so I had to add a boolean to SymWriter to avoid releasing the resources twice.

The Problem:

Problem observed when being used in coverlet:
coverlet-coverage/coverlet#1471
If an exception caused `NativePdbWriter.Write` to never be
called, it would not call `SymWriter.Close`,
which in turn meant `Marshal.ReleaseComObject` was left uncalled.

The garbage collector will eventually destroy the object
and thereby release the COM object, but that happens non-deterministically.
The COM object is holding to a file handle, which prevents
other operations on the written file until it is released.
The result was random file access issues.

The Solution:

Luckily NativePdbWriter is IDisposable. I added a call to
`writer.Close` there. But now it could be called twice,
so I had to add a boolean to SymWriter to avoid releasing
everything twice.
@OskiKervinen-MF
Copy link
Contributor Author

@jbevain Would it be better for me to report a separate Cecil issue about this, or is it enough that I link to the Coverlet issue this bug in Cecil causes?

The whole point of Dispose is to release unmanaged resources, so I would think this Pull Request makes sense without too much bookkeeping?

@jbevain jbevain merged commit 50292e7 into jbevain:master Sep 25, 2024
2 checks passed
@jbevain
Copy link
Owner

jbevain commented Sep 25, 2024

Thank you for the PR!

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.

2 participants