Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native Command Error Handling #277

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

theJasonHelmick
Copy link
Contributor

Link to original: #261

1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved
1-Draft/RFC00XX-Native-Command-Error-Handling.md Outdated Show resolved Hide resolved

### set -e/ $ErrorActionPreference

In the example below, `set -e` is not equivalent to `$ErrorActionPReference` for native commands.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In the example below, `set -e` is not equivalent to `$ErrorActionPReference` for native commands.
In the example below, `set -e` is not equivalent to `$ErrorActionPreference` for native commands.

/bin/cat ./nofile
/bin/echo "Message After failure"
/bin/echo ""
/bin/echo "With set -e : Will NOT receive message after failure"
Copy link
Member

@SteveL-MSFT SteveL-MSFT Mar 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should say "Will NOT continue script execution after failure", apply globally

```bash
bash-3.2$ cat file
#!/bin/bash
/bin/echo "Without set -o pipefail : returns 0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to clarify what 0 and 1 means for those not familiar


| Property | Definition
---------------- | -------------------
| ExitCode: | The exit code of the failed command.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some alignment issues with vertical bars

@ForNeVeR
Copy link

In Bash, it is possible to temporarily disable set -e by using command || true, e.g.

set -e
cat ./nonexistent || true
echo "Test" # will be written

From the specification, it is unclear whether a similar trick will work with $PSNativeCommandErrorAction. I believe it should be written explicitly.

@rkeithhill
Copy link

rkeithhill commented Mar 29, 2021

@ForNeVeR you would do this:

$PSNativeCommandErrorAction = $true
& {
    $PSNativeCommandErrorAction = $false
    cat ./nonexistent
    "Test" # will be written
}

cat ./nonexistent
"Will not get output"

The disabling of $PSNativeCommandErrorAction will only be valid for that scriptblock.

@theJasonHelmick When can we get this? Please let this ship in 7.2 - at least as an experimental feature!!! Maybe I should submit a PR to remove Start-NativeExecution from the PowerShell build scripts. I think the team isn't feeling the pain as much as the rest of us in the community. :-)

@joeyaiello
Copy link
Contributor

joeyaiello commented Mar 31, 2021

@PowerShell/powershell-committee reviewed this and are okay to move forward with an experimental implementation based on this RFC.

However, it's not currently committed for 7.2. As such, we're adding the up-for-grabs label.

@@ -282,8 +282,8 @@ The reported error record object will be the new type: `NativeCommandException`
### Preference variable resolves error handling conflicts

In cases where an existing script already handles non-zero native command errors, the preference
variable `$PSNativeCommandErrorAction` may be set to `$false`. Error handling behavior of the
PowerShell cmdlets is handled separately with `$ErrorActionPreference`.
variable `$PSNativeCommandUseErrorActionPreference` may be set to `$false`. Error handling behavior

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making this name longer seems like the wrong direction to go. Also, if it ends in ActionPreference then I would expect it to be of type [System.Management.Automation.ActionPreference] instead of [bool].

Copy link

@ceztko ceztko Apr 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the variable being boolean and the name ending with Preference sounds weird. The name is so long that Use gets lost while reading. PSNativeCommandErrorActionEnabled, PSEnableNativeCommandErrorAction may better highlight the implicit type of the variable. Still they are long names, though.

| Property | Definition
---------------- | -------------------
| ExitCode: | The exit code of the failed command.
| ErrorID: | `"Program {0} ended with non-zero exit code {1}"`, with the command name and the exit code, from resource string `ProgramFailedToComplete`.
Copy link

@rkeithhill rkeithhill Jul 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that concerns me is that we're kind of all over the place on terminology: NativeCommand, Program and the official get-command type is Application. That said, I'm not sure I like Application by itself e.g. Application "whoami.exe" ended with non-zero exit code 1. Application doesn't seem to be appropriate for cli utilities like whoami. Native command "whoami.exe" ended with non-zero exit code 1 seems OK.

| ErrorCategory: | `ErrorCategory.NotSpecified`.
| object: | Exit code
| Source: | The full path to the application
| ProcessInfo | Details of failed command including path, exit code, and PID

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be helpful to see the arguments a a string. Or maybe rather than command path, show the "command line". Thoughts?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the process ID of any use given that the process no longer exists?

Copy link
Contributor

@iSazonov iSazonov Jul 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be helpful to see the arguments a a string. Or maybe rather than command path, show the "command line". Thoughts?

This is not guaranteed after terminating of the process - an attempt to read a property of the Process class is likely to raise an exception. We can report reliably only current script line string or ProcessInfo as is.

Is the process ID of any use given that the process no longer exists?

This can be useful as correlation data with event logs.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After talking this over with wg-engine group we decided that process id is useful for log correlation and arguments should not be recorded because it make contain passwords / api tokens.

@rkeithhill
Copy link

@theJasonHelmick The RFC does not mention anything about this being an experimental feature. I don't think that it needs to be experimental since it is "opt-in" via setting $PSNativeCommandUseErrorActionPreference to $true. Just wanted to get clarification on this. Do you agree?

@rkeithhill
Copy link

@theJasonHelmick Have you seen this ApplicationFailedException? This covers the case where a system exception is thrown when PS tries to run the application. My concern is that someone looking at the code base may be confused by seeing ApplicationFailedException and NativeCommandException.

@joeyaiello joeyaiello added Experimental - Approved This RFC has been approved for a code submission as an experimental feature in PS/PS and removed Up-for-Grabs labels Jul 27, 2021
@joeyaiello
Copy link
Contributor

joeyaiello commented Jul 27, 2021

@rkeithhill even as an opt-in feature, it still needs to be marked as an experimental feature to denote to end-users that the design is not final and may change in the future.

Ideally, it should be code-fenced such that the opt-in isn't possible without the experimental feature turned on, but if the Maintainers agree with you that it's prohibitively difficult to do that, it should still have a placeholder experimental feature (where turning it off would do nothing) to denote the potential instability of the interface.

@joeyaiello
Copy link
Contributor

@rkeithhill agreement that, especially given what's in the docs today for ApplicationFailedException ("Defines the exception that is thrown if a native command fails", it might make sense to rename NativeCommandException to something else.

@SteveL-MSFT is suggesting NativeCommandExitException, but we're open to other possibilities.

We're also referring this RFC to the Engine WG for review.

@joeyaiello joeyaiello added WG-DevEx-Portability authoring cross-platform or cross-architecture modules, cmdlets, and scripts WG-Engine core PowerShell engine, interpreter, and runtime labels Jul 27, 2021

- When enabled (1), `$ErrorActionPreference` will affect native commands with described behavior.
- When disabled (0), `$ErrorActionPreference` will have no effect to the original behavior.
- The default value is disabled (0) to maintain backward compatibility.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- The default value is disabled (0) to maintain backward compatibility.
- The default value is 0 (disabled) to maintain backward compatibility.

@iSazonov
Copy link
Contributor

iSazonov commented Jul 28, 2021

Why not re-use ApplicationFailedException if it is about exit?

Comment on lines +44 to +46
Simply relaying the errors through the error stream isn't the solution. The example itself doesn't
support all cases as `$?` can be false from a cmdlet or function error, making `$LASTEXITCODE`
stale.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example itself doesn't support all cases

What example is it referring to? The if ($LASTEXITCODE -ne 0) { ... } one right above? If so, it's not clear to me how $? will affect that example, and can you maybe elaborate a bit more on how $LASTEXITCODE would be stale?

@JamesWTruher
Copy link
Contributor

@theJasonHelmick - would you please confirm that the implemented experimental feature matches what is written here?

@per-oestergaard
Copy link

Is this now part of PowerShell as an experimental features (cannot find it in 7.2.2) or when will it come?

@rkeithhill
Copy link

It's in the current 7.3.0 preview - PSNativeCommandErrorActionPreference. After enabling the feature and restarting pwsh, try this:

whoami -xyzzy
get-date
& {
    $ErrorActionPreference = 'Stop'
    $PSNativeCommandUseErrorActionPreference = $true
    whoami -xyzzy
    get-date
}

@jtmoon79
Copy link

jtmoon79 commented Dec 2, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Committee-Reviewed Experimental - Approved This RFC has been approved for a code submission as an experimental feature in PS/PS WG-DevEx-Portability authoring cross-platform or cross-architecture modules, cmdlets, and scripts WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

Successfully merging this pull request may close these issues.