Standard Unix signal SIGPIPE is sent to processes that attempt to write to a broken pipe, i.e., to a pipe whose reading process has terminated.
This is not necessarily an error condition, as standard utilities such as head simply exit once they've received enough input, which causes the upstream command to eventually receive SIGPIPE on attempting to write to a pipe that no one's reading from anymore.
The default SIGPIPE behavior on Unix-like platforms is to quietly terminate the writing process on attempting to write to a broken pipe, and to have it report exit code 141 (which is 128 (termination by signal) + 13, 13 being SIGPIPE's number).
This behavior is unexpectedly deactivated in PowerShell for child processes too, because the SIGPIPE signal is effectively turned off (ignored).
In short: External utilities may exhibit unexpected behavior when run from PowerShell.
Note:
- The problem may ultimately stem from a layer below PowerShell (CoreFx / CoreCLR)
- It's also worth looking into what additional signals are affected.
- It makes sense for PowerShell itself to custom-handle
SIGPIPE (so that it isn't quietly terminated as a whole when writing to a broken pipe), but it should restore default signal handling for child processes, i.e., external programs.
Steps to reproduce
On Unix-like platforms:
Expected behavior
That is, head -n 1 should receive the 1st y line output by utility yes, exit, and eventually cause yes to be terminated quietly due to attempting to write to a broken pipe, so that the next statement 'done' is executed.
Actual behavior
y # "HANGS" here - `yes` keeps running
That is, yes never receives SIGINT and therefore keeps running indefinitely.
Environment data
PowerShell Core v6.2.0-preview.2 on macOS 10.14.1
PowerShell Core v6.2.0-preview.2 on Ubuntu 18.04.1 LTS
Standard Unix signal
SIGPIPEis sent to processes that attempt to write to a broken pipe, i.e., to a pipe whose reading process has terminated.This is not necessarily an error condition, as standard utilities such as
headsimply exit once they've received enough input, which causes the upstream command to eventually receiveSIGPIPEon attempting to write to a pipe that no one's reading from anymore.The default
SIGPIPEbehavior on Unix-like platforms is to quietly terminate the writing process on attempting to write to a broken pipe, and to have it report exit code141(which is128(termination by signal) +13,13beingSIGPIPE's number).This behavior is unexpectedly deactivated in PowerShell for child processes too, because the
SIGPIPEsignal is effectively turned off (ignored).In short: External utilities may exhibit unexpected behavior when run from PowerShell.
Note:
SIGPIPE(so that it isn't quietly terminated as a whole when writing to a broken pipe), but it should restore default signal handling for child processes, i.e., external programs.Steps to reproduce
On Unix-like platforms:
Expected behavior
That is,
head -n 1should receive the 1styline output by utilityyes, exit, and eventually causeyesto be terminated quietly due to attempting to write to a broken pipe, so that the next statement'done'is executed.Actual behavior
y # "HANGS" here - `yes` keeps runningThat is,
yesnever receivesSIGINTand therefore keeps running indefinitely.Environment data