Skip to content

Finalizers may crash the application #16

@Rantanen

Description

@Rantanen

Several finalizers end up accessing managed finalizable resources. An example would be FileDownloadLocation, which accesses DirectoryInfo through its finalizer.

00000020`208ff1d0 00007ffd`0f2dda49 mscorlib_ni!System.IO.__Error.WinIOError+0x119
00000020`208ff220 00007ffd`0f3d5875 mscorlib_ni!System.IO.FileSystemEnumerableIterator`1[[System.__Canon, mscorlib]].CommonInit+0x1a5
00000020`208ff4d0 00007ffd`0f3d5493 mscorlib_ni!System.IO.FileSystemEnumerableIterator`1[[System.__Canon, mscorlib]]..ctor+0x203
00000020`208ff570 00007ffd`0f2f227d mscorlib_ni!System.IO.DirectoryInfo.InternalGetFiles+0x5d
00000020`208ff5e0 00007ffc`de4a4ff9 UNKNOWN!MFilesAPI.Extensions.FileDownloadLocation.CleanTemporaryFiles+0x49
00000020`208ff630 00007ffc`de4a4f72 UNKNOWN!MFilesAPI.Extensions.FileDownloadLocation.Dispose+0x22
00000020`208ff670 00007ffc`de4a4f30 UNKNOWN!MFilesAPI.Extensions.DisposableBase.Finalize+0x10

In the stack above the FileDownloadLocation is being finalized and it ends up executing CleanTemporaryFiles that accesses the managed DirectoryInfo. When implementing the Dispose(bool) pattern, the types should not touch managed objects when the boolean parameter indicates the call is coming through the finalizer.

If the method call comes from a finalizer, only the code that frees unmanaged resources should execute. The implementer is responsible for ensuring that the false path doesn't interact with managed objects that may have been disposed. This is important because the order in which the garbage collector disposes managed objects during finalization is nondeterministic.

Implementing dispose

It's also worth noting, that in .NET 5/.NET Core the finalizers are skipped during application shutdown.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions