Skip to content

Turn SystemError.from_errno into a macro#15874

Merged
straight-shoota merged 6 commits intomasterfrom
ci/fix/system_error-constructor-errno.value
Jun 10, 2025
Merged

Turn SystemError.from_errno into a macro#15874
straight-shoota merged 6 commits intomasterfrom
ci/fix/system_error-constructor-errno.value

Conversation

@straight-shoota
Copy link
Member

SystemError.from_errno calls Errno.value to retrieve the system error value from the last lib call.
But this happens in the body of the method which only executes after its arguments are evaluated (for example building the error message). This can lead to a change in Errno.value which .from_errno would then mistake for the original error.
In order to fix this, we must query Errno.value immediately after the lib call.

Changing .from_errno into a macro achieves that because it expands into a call to Errno.value before constructing the actual error object and its arguments.

We need to change the deprecated from_errno method which receives an Errno value as well because the macro would shadow the method.

One downside of the macro approach is that it won't work with file-private error types (#15496 (comment)). But this is probably not a very relevant use case.

If this is accepted, I'll do the same change to SystemError.from_winerror and SystemError.from_wsa_error.

Resolves #15496

@straight-shoota straight-shoota self-assigned this Jun 4, 2025
@straight-shoota straight-shoota added kind:bug A bug in the code. Does not apply to documentation, specs, etc. breaking-change May have breaking effect in some edge cases. Mostly negligible, but still noteworthy. topic:stdlib:system labels Jun 4, 2025
@HertzDevil
Copy link
Contributor

The actual method that resolves #15496 is .from_winerror. The Win32 code in stdlib pretty much never uses errno

@straight-shoota straight-shoota added kind:breaking Intentional breaking change with significant impact. Shows up on top of the changelog. and removed kind:bug A bug in the code. Does not apply to documentation, specs, etc. breaking-change May have breaking effect in some edge cases. Mostly negligible, but still noteworthy. labels Jun 5, 2025
straight-shoota and others added 3 commits June 5, 2025 22:46
This ensures we capture `Errno.value` right away and it cannot be
influenced by other code producing the arguments.
Co-authored-by: Quinton Miller <nicetas.c@gmail.com>
@straight-shoota straight-shoota force-pushed the ci/fix/system_error-constructor-errno.value branch 2 times, most recently from e7a4962 to bfe0758 Compare June 5, 2025 21:21
@straight-shoota straight-shoota force-pushed the ci/fix/system_error-constructor-errno.value branch from bfe0758 to e48f1d1 Compare June 5, 2025 22:14
@straight-shoota straight-shoota marked this pull request as ready for review June 6, 2025 10:38
# The system message corresponding to the OS error value amends the *message*.
# Additional keyword arguments are forwarded to the exception initializer `.new_from_os_error`.
macro from_errno(message, **opts)
# This is a macro in order to retrieve `Errno.value` first before evaluating `message` and `opts`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Polish: maybe move this comment outside of the macro, and be more general:

The following are macros so we can get the errno or winerror before
evaluating message and opts that may change the errno or winerror value.

@straight-shoota straight-shoota added this to the 1.17.0 milestone Jun 6, 2025
@straight-shoota straight-shoota merged commit cefe508 into master Jun 10, 2025
74 checks passed
@straight-shoota straight-shoota deleted the ci/fix/system_error-constructor-errno.value branch June 10, 2025 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind:breaking Intentional breaking change with significant impact. Shows up on top of the changelog. topic:stdlib:system

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC.malloc resets WinError.value on MinGW-w64

3 participants