Skip to content

Instantly share code, notes, and snippets.

@Zetanova
Last active May 2, 2024 22:24
Show Gist options
  • Save Zetanova/9e1a0d5e35d9ce876840b9d9b22445b3 to your computer and use it in GitHub Desktop.
Save Zetanova/9e1a0d5e35d9ce876840b9d9b22445b3 to your computer and use it in GitHub Desktop.
Use Signal 'ctrl+c' as CancellationTokenSource for sync-over-async calls
using namespace System.Linq.Expressions
#class to register on posix signal and provide a cancellation token
#many signal are working under windows (SIGINT, SIGQUIT ...)
class SignalToken : System.IDisposable {
hidden [System.Threading.CancellationTokenSource]$cts
hidden [System.Runtime.InteropServices.PosixSignalRegistration]$reg
[System.Runtime.InteropServices.PosixSignal]$Signal = [System.Runtime.InteropServices.PosixSignal]::SIGINT
[System.Threading.CancellationToken]$Token
SignalToken() {
$this.Reset()
}
SignalToken([System.Runtime.InteropServices.PosixSignal]$signal) {
$this.Signal = $signal
$this.Reset()
}
[void] Reset() {
if(!($this.cts -and $this.cts.TryReset())) {
$this.cts = new-object System.Threading.CancellationTokenSource
$handler = [Expression]::Lambda(
[System.Action[System.Runtime.InteropServices.PosixSignalContext]],
[Expression]::Block(
[Expression]::Call([Expression]::Constant($this.cts), [System.Threading.CancellationTokenSource].GetMethod("Cancel", [Type]::EmptyTypes))
),
[ParameterExpression[]](
[Expression]::Variable([System.Runtime.InteropServices.PosixSignalContext])
)
).Compile()
$this.reg = [System.Runtime.InteropServices.PosixSignalRegistration]::Create($this.Signal, $handler)
$this.Token = $this.cts.Token
}
}
[void] Dispose() {
$this.reg.Dispose()
$this.cts.Dispose()
}
}
#script block is for demonstation purposes
function Invoke-Demo {
param()
begin {
Write-Host "begin"
$signal = [SignalToken]::new()
}
process {
Write-Host "locking for 10sec, press ctrl+c to cancel"
[System.Threading.Tasks.Task]::Delay(10000, $signal.Token).GetAwaiter().GetResult()
Write-Host "no cancelletion"
#demo how to reuse cancellation source
if($signal.Token.IsCancellationRequested) {
Write-Host "recreate used cts"
$signal.Reset()
}
}
end {
Write-Host "end"
}
clean {
Write-Host "clean"
$signal.Dispose()
}
}
Invoke-Demo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment