GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-106672: C API: Report indiscriminately ignored errors by serhiy-storchaka · Pull Request #106674 · python/cpython Conversation
|
|
Can you please list affected functions? Is there a way to mute these warnings if an application is affected by this change but the maintainer is not available in the short term to fix these issues? These APIs were ignoring silently errors for years. Maybe we need a command line option and/or environment variable to set an unraisable hook which... Does nothing. In code, I suppose that it's easy to do: import sys def silence_errors(args): pass sys.unraisablehook=silence_errors |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I made a similar change in Python 3.13 io module: close() errors are now logged. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I listed them in the NEWS entry. Will add them to the commit message too. There are no new reports in the CPython tests, so at least CPython code is almost clear. They can still occur if you press Ctrl-C or run program in memory constricted environment, but it is very unlikely. I think that the problem of silencing unraisable exception messages is a separate issue. It may be even not too important issue if such messages are rare. In addition to "silence error" I would consider adding option for "abort immediately". |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Oh sure, you can abort the process on the first unraisable exception: import signal, sys def abort_hook(unraisable): signal.raise_signal(signal.SIGABRT) sys.unraisablehook = abort_hook A better implementation may want to log the exception before 😁 Maybe by calling the old hook. At the beginning, it was proposed to always crash the process. Are you suggesting command line and env var to get his behavior? pytest now catchs these unraisable exceptions. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Oh sorry I miss it, thanks. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Would it be possible to suggest a fix in the warning? Like using an API which report errors? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
It is a different issue, but I would be interested in such feature. Not that I need it now, but if I need it, it would be useful.
On one hand, it would help the author of the extension. On other hand, it will overwhelm the user of the extension with not useful information. Should I keep the current more general description?
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I would prefer to suggest using a different function to avoid such warning. About the phrasing, you may write "...; consider using xxx()". I'm also fine with the shorter error message. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Unrelated note: we should consider making _PyErr_WriteUnraisableMsg() a public function. But i'm not sure about its API. Is the error message format easy to get?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
I would prefer richer API, similar to |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
That sounds like a good idea :-) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| { | ||
| return dict_getitem(op, key, | ||
| "in PyDict_GetItem(); consider using " | ||
| "PyDict_GetItemWithError()"); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
There will be new PyDict_GetItemRef().
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if (kv == NULL) { | ||
| PyErr_Clear(); | ||
| _PyErr_WriteUnraisableMsg( | ||
| "in PyDict_GetItemString()", NULL); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
No replacement currently. There will be new PyDict_GetItemRefString().
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| /* XXX Suppress a new exception if it was raised and restore | ||
| * the old one. */ | ||
| if (_PyErr_Occurred(tstate)) { | ||
| _PyErr_WriteUnraisableMsg("in PySys_GetObject()", NULL); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
No replacement currently.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm waiting until PyDict_GetItemRef() is accepted to consider proposing a variant for PySys_GetObject(). I'm tracking functions returning borrowed references and replacement at: https://pythoncapi.readthedocs.io/bad_api.html#functions
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| /* XXX Suppress a new exception if it was raised and restore | ||
| * the old one. */ | ||
| if (_PyErr_Occurred(tstate)) { | ||
| _PyErr_WriteUnraisableMsg("in PySys_GetObject()", NULL); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm waiting until PyDict_GetItemRef() is accepted to consider proposing a variant for PySys_GetObject(). I'm tracking functions returning borrowed references and replacement at: https://pythoncapi.readthedocs.io/bad_api.html#functions
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if (rc == 0 && PyErr_Occurred()) { | ||
| _PyErr_WriteUnraisableMsg( | ||
| "in PyMapping_HasKeyString(); consider using " | ||
| "PyMapping_GetOptionalItemString() or PyMapping_GetItemString()", |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This case is very subtle and the error message is not heplful. It's non-obvious to me that the exception was already set before the function was called.
Maybe the error message should be something like: "Ignore exception set before calling in PyMapping_HasKeyString()".
Instead of "Exception ignored in PyMapping_HasKeyString()".
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately _PyErr_WriteUnraisableMsg() does not support this.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
LGTM. It may annoy people but there is a way to silence these warnings, so i'm fine with it.
Error messages can be enhanced, but the current API to log unraisable exception is too limited. It's ok the revisit them later.
I dislike ignoring errors, it can silence important errors. So this change is a nice step forward.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Do you need help to solve conflicts? I approved your PR but you didn't merge it yet. Do you plan further changes? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I could merge this PR long time ago, but I wanted to do some things before to make this PR better:
Of course it can be merged before implementing all steps above, but then we will need to return to this code to improve it. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Updated, improved warning messages. Adding a replacement for |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
| if (v) { | ||
| Py_DECREF(v); | ||
| return 1; | ||
| PyObject *dummy; |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename to 'item' or 'value'.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Done.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
If these warnings become a performance issue later, maybe we can compute some fixed strings as static strings, like _Py_STR() API. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
In the What's New, would it be possible to mention recommended replacement function(s), maybe as a list (func: replace)? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Co-authored-by: Victor Stinner <[email protected]>
They are already mentioned in the documentation for corresponding functions. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| PyErr_FormatUnraisable( | ||
| "Ignore exception set before calling in PyMapping_HasKeyString(); " | ||
| "consider using PyMapping_HasKeyStringWithError(), " | ||
| "PyMapping_GetOptionalItemString() or PyMapping_GetItemString()"); |
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Can these 3 functions be called with an exception set? They don't override the exception? That sounds surprising. I would prefer suggesting to not call the function with an exception set. What do you think?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Got catch. Indeed, PyMapping_GetOptionalItemString() can only return 0 if no exception is set, so this condition is always false. Also, the alternative functions also can clear exceptions.
I think that we should classify the C API by classes:
There may be more classes.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
In the general case, to write safe code handling a raised exception, I think the safest option is to keep the exception aside using PyErr_GetRaisedException(). Maybe today some functions are perfectly fine and never override the currently raised exception. But what if tomorrow their implementation changes, and they may start to clear the currently raised exception?
In Python, in an except: block, there is no "currently raised exception" in the C level, even if sys.exc_info() returns the exception. The difference between PyThreadState.exc_info and PyThreadState.current_exception is subtle.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This is why it should be clearly documented.
Obviously you can call PyErr_Occurred(), PyErr_GetRaisedException() or PyErr_WriteUnraisable() when an exception is set.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…nGH-106674) Functions which indiscriminately ignore all errors now report them as unraisable errors.
…nGH-106674) Functions which indiscriminately ignore all errors now report them as unraisable errors.
…nGH-106674) Functions which indiscriminately ignore all errors now report them as unraisable errors.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.