Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ParallelKit.Harness.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ function New-JobList {
}

$cmdExe = Join-Path $env:SystemRoot "System32\cmd.exe"
# Whichever PowerShell is running the harness (powershell.exe or pwsh.exe),
# for the tests that need a fresh process of the same version.
$selfExe = [System.Diagnostics.Process]::GetCurrentProcess().MainModule.FileName
$pingExe = Join-Path $env:SystemRoot "System32\ping.exe"

# A user function the workers share.
Expand Down Expand Up @@ -688,6 +691,17 @@ $probeThreads = 0
if ($probe.Stdout -match 'threads=(\d+)') { $probeThreads = [int]$Matches[1] }
Test-Assert ($probeThreads -ge 128) ("and raises the thread pool by itself (minimum " + $probeThreads + ")")

# Loading the kit in Constrained Language Mode fails with a message that
# says so. Needs a fresh process: the mode can't be set back.
$clmScript = Join-Path $env:TEMP ("pk-clm-" + [guid]::NewGuid().ToString("N") + ".ps1")
[System.IO.File]::WriteAllText($clmScript, @"
`$ExecutionContext.SessionState.LanguageMode = 'ConstrainedLanguage'
try { . '$kitPath'; Write-Output 'loaded' } catch { Write-Output ('error: ' + `$_) }
"@)
$clm = Invoke-PkProcessWithTimeout -FilePath $selfExe -Arguments ('-NoProfile -ExecutionPolicy Bypass -File "' + $clmScript + '"') -TimeoutMs 60000
[System.IO.File]::Delete($clmScript)
Test-Assert ($clm.Stdout -like '*ConstrainedLanguage mode, but the kit needs FullLanguage*') ("loading in Constrained Language Mode fails with a message naming the problem (" + ([string]$clm.Stdout).Trim() + ")")

# The dispatcher sizes the pool for its own concurrency.
$feed = @{ Given = $false }
$null = Invoke-PkProcessDispatch -MaxConcurrent 100 -GroupProvider { return $null } -JobBuilder { param($g) } -JobFinalize { param($j, $p) }
Expand Down
8 changes: 8 additions & 0 deletions ParallelKit.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
# function called from inside a .GetNewClosure()'d block can see an empty
# $script: scope, and a static has no scope to lose.

# Everything below needs Add-Type, which Constrained Language Mode blocks with
# an error that doesn't say why. Say why.
if ($ExecutionContext.SessionState.LanguageMode -ne 'FullLanguage') {
throw ("ParallelKit: this PowerShell session runs in " + $ExecutionContext.SessionState.LanguageMode + " mode, but the kit needs FullLanguage " +
"(it compiles C# with Add-Type). This is usually set by AppLocker or Windows Defender Application Control policy. " +
"Ask whoever manages the machine to allow this script, or run it where that policy doesn't apply.")
}

# ==============================================================================
# Native types (guarded so the file can be dot-sourced more than once)
# ==============================================================================
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ Other pieces: `Request-PkAbort` triggers the same abort from code. `Test-PkAbort
## Limits

- Windows PowerShell 5.1, Windows only (console and Job Object APIs).
- It needs FullLanguage mode, since it compiles a little C# with `Add-Type` when loaded. On a machine locked down to Constrained Language Mode (usually by AppLocker or Windows Defender Application Control), loading it fails with a message saying so. Some endpoint security products also flag scripts that compile code calling Windows APIs at runtime; if yours blocks the kit, that's the likely reason.
- After changing `ParallelKit.ps1` itself, start a new PowerShell window. A session keeps the kit's compiled parts until it closes; the kit tells you if it finds an older copy loaded.
- One run at a time per process. The abort state is shared. A nested `Invoke-PkRun` just runs inside the outer one.
- A worker stuck inside a long .NET call can't be interrupted. Force-stop stops waiting for it and returns. The worker is NOT killed: once that call returns it can carry on to the end of its script. Before any step that can't be undone (deleting a source file, say), have the worker check `Test-PkCancelRequested` and skip the step if it's true.
Expand Down
Loading