question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Thread safe class method defined in Powershell hangs inside a Lazy inside a ConcurrentDictionary

See original GitHub issue

Prerequisites

Steps to reproduce

I have a thread safe class method (it’s static and empty) that is hanging when called inside of a System.Lazy initializer inside of a System.Collections.Concurrent.ConcurrentDictionary when used with ForEach-Object -Parallel. Calling a normal dotnet method works fine (e.g. [System.Convert]::ToString(132456, 2)), but my [Dead]::Lock() method call hangs.

This is as far as I was able to strip my repro code down while still causing the hang:

#Requires -Version 7

Write-Host "Starting job`n"

$dict = [System.Collections.Concurrent.ConcurrentDictionary[string, System.Lazy[string]]]::new()

$job = 1..16 | ForEach-Object -AsJob -ThrottleLimit 16 -Parallel {
    $threadNum = $_
    $dict = $using:dict

    class Dead {
        # This method should be thread safe(?)
        static [void] Lock() {
        }
    }

    [System.Console]::WriteLine("Starting thread #$threadNum")

    $lazy = $dict.GetOrAdd("same key", [System.Lazy[string]]::new(
        {
            # Calling this method causes the script to hang, even though it should(?) be thread safe
            [Dead]::Lock()

            $okToCall = [System.Convert]::ToString(132456, 2)
            return ""
        },
        [System.Threading.LazyThreadSafetyMode]::ExecutionAndPublication))

    [void]$lazy.Value

    [System.Console]::WriteLine("Completed thread #$threadNum")
}
try {
    while (!$job.Finished.WaitOne(1000)) {
        Write-Host "$(Get-Date): Waiting"
    }
    $job | Receive-Job

    Write-Host "`nFinished job`n"
} finally {
    $job | Stop-Job
}

Note: you may need to run this a bunch of times to actually see the hang. I’m also running this without my profile to ensure that’s not interfering: pwsh.exe -NoProfile -File $Home\OneDrive\Scripts\bug.ps1

I’ve had independent verification of the hang from at least one other user.

Expected behavior

PS C:\> pwsh.exe -NoProfile -File $Home\OneDrive\Scripts\bug.ps1
Starting job

Starting thread #1
Starting thread #2
Starting thread #3
Starting thread #4
Starting thread #5
Starting thread #6
Starting thread #7
Starting thread #8
Starting thread #9
Starting thread #10
Starting thread #11
Starting thread #12
Starting thread #13
Starting thread #14
Starting thread #15
Starting thread #16
Completed thread #2
Completed thread #6
Completed thread #9
Completed thread #13
Completed thread #3
Completed thread #1
Completed thread #4
Completed thread #5
Completed thread #7
Completed thread #8
Completed thread #10
Completed thread #11
Completed thread #12
Completed thread #14
Completed thread #15
Completed thread #16

Finished job

PS C:\>

Actual behavior

PS C:\> pwsh.exe -NoProfile -File $Home\OneDrive\Scripts\bug.ps1
Starting job

Starting thread #2
Starting thread #1
Starting thread #3
Starting thread #4
Starting thread #5
Starting thread #6
Starting thread #7
Starting thread #8
Starting thread #9
Starting thread #10
Starting thread #11
Starting thread #12
Starting thread #13
Starting thread #14
Starting thread #15
Starting thread #16
10/10/2022 11:52:52: Waiting
10/10/2022 11:52:53: Waiting
10/10/2022 11:52:54: Waiting
10/10/2022 11:52:55: Waiting
10/10/2022 11:52:56: Waiting
10/10/2022 11:52:57: Waiting
10/10/2022 11:52:58: Waiting
10/10/2022 11:52:59: Waiting
10/10/2022 11:53:00: Waiting
10/10/2022 11:53:01: Waiting
10/10/2022 11:53:02: Waiting

Error details

No response

Environment data

Name                           Value
----                           -----
PSVersion                      7.2.6
PSEdition                      Core
GitCommitId                    7.2.6
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:9 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
SeeminglySciencecommented, Oct 10, 2022

Thanks! I don’t think I ever would have found that existing issue. 😃

Oh yeah, you’re good, we just mark it for tracking purposes 😃 We would always much prefer duplicates over issues going unreported ❤️

Especially with issues as impossible to search for as this 😁

1reaction
SeeminglySciencecommented, Oct 10, 2022

This is a known issue (and somewhat by design) for static methods. Very recently a PR was merged adding a way to strip runspace affinity for a class. Once that makes it to a preview, that will be the recommended way of handling it.

In earlier versions you can move to instance methods and use the work around described in https://github.com/PowerShell/PowerShell/issues/3651#issuecomment-306968528

Read more comments on GitHub >

github_iconTop Results From Across the Web

Making ConcurrentDictionary GetOrAdd thread safe using ...
This post explores the GetOrAdd function of ConcurrentDictionary, the level of thread safety it provides, and ways to add additional ...
Read more >
Are non-concurrent collections safe inside ...
My thought is that as long as the highest level collection is configured to be concurrent/thread safe, it doesn't matter if the nested ......
Read more >
Using Lazy and ConcurrentDictionary to ensure a thread- ...
In this post, Mike Larah discusses how to ensure your C# collections are thread-safe, only run-once, and are lazy-loaded.
Read more >
Add and Remove Items from a ConcurrentDictionary
Read an example of how to add, retrieve, update, and remove items from the ConcurrentDictionary collection class in .NET.
Read more >
Untitled
Alama bakmie keliinici di blok m, How to measure inside leg of jeans, ... Apa yang dimaksud dengan business process improvement, Circuit queen...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found