Describe the bug
This issue reproduces only on PowerShell Core -- has not (yet) been reproduced on desktop.
To Reproduce
Repro isn't 100% clear, but seems to be in cases where a thread created by module A uses Script-Object to create an object in module B:
In outside of module M use Start-ThreadJob to create a new job with scriptblock that contains code that invokes the a static method on a scriptclass type defined outside of module M that uses New-ScriptObject to create and return a new object of a type hosted by module M
Immediately use wait-job to wait for the job
The code will hang -- ctrl-c works to get out of it, but get-job will show the job is still running, and if you then try to exit the powershell session with the exit command it will hang. Given the latter behavior, while this is an issue with the scriptclass module, there is clearly something broken in PowerShell itself -- nothing we write using pure PowerShell should actually hard hang the shell.
I've been able to get the following repro on Windows powershell core (I've seen these hangs on Linux also, so should be the same there):
import-module scriptclass
import-module moduleM # A module that exposes a ScriptClass type TypeT
# As implied by the fact that we imported moduleM, the remaining code is not part of moduleM
scriptclass MyType {
static {
function GetTypeInstance { new-so TypeT } # TypeT defined in moduleM
}
}
# Types defined on this thread aren't visible in threads created by Start-ThreadJob, so you need
# to pass in the class object to make it accessible
$newJob = Start-ThreadJob { param($inputType) $inputType.GetTypeInstance() } -ArgumentList $::.MyType; write-host 'startedjob'; $newjob | wait-job
write-host "Successfully returned the type"
Expected behavior
The code should return quickly with an instance of ScriptClass object type TypeB and the following output in the console:
startedjob
Successfully returned the type
Any subsequent invocations of get-job should show this job with a state Completed
Actual behavior is a hang -- the final message is never printed, so the output is simply the first line startedjob. You can break out of the hang with CTRL-C. However, get-job shows that the job is still running!
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
2 Job2 ThreadJob Running False PowerShell param($inputType) $inpu…
Additionally, if you then use exit to exit PowerShell altogether, that hangs! This last behavior indicates a bug in PowerShell itself.
Note that the bug does not seem to reproduce reliabily if you don't do the wait-job immediately after the start-threadjob, indicating a race condition of some sort.
I encountered this situation on a CI pipeline where it repro'd reliably when I added a very specific test. Rearranging the code made it seem to go away (at first I though it was related to making outgoing http requests in the other thread, even though that had worked reliably for years). Eventually I was able to isolate the behavior and come up with this very focused repro.
The workaround: don't use new-scriptobject in a threadjob (or maybe only use objects that are not exported from a module).
Describe the bug This issue reproduces only on PowerShell Core -- has not (yet) been reproduced on desktop.
To Reproduce Repro isn't 100% clear, but seems to be in cases where a thread created by module A uses Script-Object to create an object in module B:
The code will hang -- ctrl-c works to get out of it, but get-job will show the job is still running, and if you then try to exit the powershell session with the
exit
command it will hang. Given the latter behavior, while this is an issue with thescriptclass
module, there is clearly something broken in PowerShell itself -- nothing we write using pure PowerShell should actually hard hang the shell.I've been able to get the following repro on Windows powershell core (I've seen these hangs on Linux also, so should be the same there):
Expected behavior The code should return quickly with an instance of ScriptClass object type
TypeB
and the following output in the console:Any subsequent invocations of
get-job
should show this job with a stateCompleted
Actual behavior is a hang -- the final message is never printed, so the output is simply the first line
startedjob
. You can break out of the hang with CTRL-C. However, get-job shows that the job is still running!Additionally, if you then use
exit
to exit PowerShell altogether, that hangs! This last behavior indicates a bug in PowerShell itself.Note that the bug does not seem to reproduce reliabily if you don't do the
wait-job
immediately after thestart-threadjob
, indicating a race condition of some sort.I encountered this situation on a CI pipeline where it repro'd reliably when I added a very specific test. Rearranging the code made it seem to go away (at first I though it was related to making outgoing http requests in the other thread, even though that had worked reliably for years). Eventually I was able to isolate the behavior and come up with this very focused repro.
The workaround: don't use new-scriptobject in a threadjob (or maybe only use objects that are not exported from a module).