dahall / Vanara

A set of .NET libraries for Windows implementing PInvoke calls to many native Windows APIs with supporting wrappers.
MIT License
1.75k stars 190 forks source link

`HRESULT.ToString()` is not thread-safe due to mutable global state. #419

Closed ArchibaldMacdonald-cyacomb closed 11 months ago

ArchibaldMacdonald-cyacomb commented 11 months ago

Describe the bug and how to reproduce

HRESULT.ToString() relies on a string cache that is not thread-safe, so when calling HRESULT.ToString() from different threads, an exception is triggered when updating this cache.

What code is involved

This can be easily triggered with the following snippet:

using System.Diagnostics;
using Vanara.PInvoke;

var a1 = Task.Run(() => { for (int i = 0; i < 100; ++i) { Debug.Print(new HRESULT().ToString()); } });
var a2 = Task.Run(() => { for (int i = 0; i < 100; ++i) { Debug.Print(new HRESULT().ToString()); } });
Task.WaitAll(a1, a2);

Expected behavior

Two separate HRESULT objects, that exist separately on different threads, should not interfere with one another.

Screenshots

Code that triggers exception: image

Exception source:

image

dahall commented 11 months ago

I just pushed a new version 3.4.16 that should fix this. Please test and confirm.

ArchibaldMacdonald-cyacomb commented 11 months ago

Thanks for the fast turnaround. I can confirm it is fixed.