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-111997: C-API for signalling monitoring events by iritkatriel · Pull Request #116413 · python/cpython Conversation
|
I think we should provide CodeLike in some form, but for now I put it in the text file so we can talk about how and where we want it to be. The offset to location mapping should also be part of this.
@markshannon did you intend for these to be private? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
My thinking was that it is better to keep any function private unless we need it to be public. It sounds like they need to be public. How about this?
Something like this: #ifndef Py_LIMITED_API static inline int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset) { if (state->active) return _PyMonitoring_FirePyStartEvent(state, codelike, offset); else return 0; } #else extern int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, uint32_t offset); #endif |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
The "code like" object is entirely opaque to the monitoring machinery. As far as it is concerned, a location is a pair of an object and an integer index. So, no C struct, but a Python abstract base class. |
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.
There was an error while loading. Please reload this page.
|
Looking through the code for the interpeter implementation of firing events about exceptions, it looks like the exception is usually passed explicitly. And considering that the concept of there being one (and only one) "current exception" doesn't always make sense, I think all API functions for events where the callback receives the exception should have an exception parameter. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
What do you mean? I see all those functions call |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Good question. I mean that the exception is passed explicitly to any callback function. From PEP 669:
Passing the exception as an argument might require the user of the API to do a bit more work, but it removes a lot of uncertainty about the "current exception". For example, consider a C extension that is about to raise an exception. To raise an exception, it must have a reference to that exception. Since it has a reference to the exception is straightforward to pass it as an argument: PyObject *exception; /* Strong reference to the exception to be raised */ if (PyMonitoring_FireRaiseEvent(state, codelike, offset, exception) < 0) { /* Would could chain the exceptions, but I'm lazy, so I'm just going to discard it */ Py_DECREF(exception); return NULL; } PyErr_SetRaisedException(exception); return NULL; |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
The c api also passes the exception to the callbacks. It's the Fire functions that we removed it from. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
For example, consider a C extension that is about to raise an exception. To raise an exception, it must have a reference to that exception.
I would rather think that the authors would use something like PyErr_SetString() to create the exception, and then be annoyed by having to do the "get it, fire, set it back" dance. It seems unlikely that exception code manually creates an exception instance.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
We need to merge this pretty much now, so last call for strong objections. Otherwise we can iterate via bugfixes. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
No strong objections. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Does Does CPython really create a EDIT: it seems that it does: Lines 289 to 317 in 5248596
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
That said, this is a detail that can still be decided during the beta phase, so feel free to merge this PR as it is if there's remaining need for discussion. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Yes, but only if you ask for it (it has zero cost if you don't ask for it, thanks to the adaptive interpreter) https://github.com/python/cpython/blob/main/Python/bytecodes.c#L291 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
It seems that you already found that 🙂 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Ok … then I think it would be best if CPython's monitoring infrastructure created a Basically, move the existing code from the byte code handlers all the way to the other side into the notification mechanism. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
That might suggest that the signature for the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I'll merge, please create an issue to iron out the StopIteration business. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Or discuss it on #111997. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
In order to avoid any confusion about blocker tickets during the beta release, I created a new ticket to discuss the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…on (GH-103083) * The majority of the monitoring code is in instrumentation.c * The new instrumentation bytecodes are in bytecodes.c * legacy_tracing.c adapts the new API to the old sys.setrace and sys.setprofile APIs
| } | ||
| assert(args[2] == NULL); | ||
| args[2] = offset_obj; | ||
| Py_ssize_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET; |
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.
I think this is incorrect. We call call_one_instrument() below, which passes nargsf on into _PyObject_VectorcallTstate() as a Py_ssize_t, but that actually wants a size_t, thus receiving a huge positive value:
#8 0x00005555558b0e7f in _PyObject_VectorcallTstate (kwnames=0x0, nargsf=9223372036854775811, args=0x7fffffffd048, callable=0x7ffff650d380, tstate=0x555555c2a050 <_PyRuntime+294032>) at ./Include/internal/pycore_call.h:168
#9 call_one_instrument (event=5, tool=<optimized out>, nargsf=-9223372036854775805, args=0x7fffffffd048, tstate=0x555555c2a050 <_PyRuntime+294032>, interp=<optimized out>) at Python/instrumentation.c:907
#10 capi_call_instrumentation (state=state@entry=0x7fffffffd0fa, codelike=codelike@entry=0x7ffff744cba0, offset=offset@entry=5, args=args@entry=0x7fffffffd040, nargs=<optimized out>, nargs@entry=3, event=event@entry=5) at Python/instrumentation.c:2457
#11 0x00005555558b6893 in _PyMonitoring_FireLineEvent (state=state@entry=0x7fffffffd0fa, codelike=codelike@entry=0x7ffff744cba0, offset=offset@entry=5, lineno=lineno@entry=5) at Python/instrumentation.c:2569
#12 0x00007ffff65f152c in PyMonitoring_FireLineEvent (lineno=5, offset=5, codelike=0x7ffff744cba0, state=0x7fffffffd0fa) at /opt/python3.13/include/python3.13d/cpython/monitoring.h:162
I think we should be using a size_t here directly and cast nargs before or-ing it.
That problem already seems to exist in the original sys.monitoring implementation. I've now reported it in 411b1692811b#r142178099
Edit: I now figured out that it's a minor issue, though. It gives the correct results. It still seems error prone to pass a Py_ssize_t around here because it no longer has a signed value from the moment where we or it with the argument flag.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| PyObject *args[4] = { NULL, NULL, NULL, lno }; | ||
| int res= capi_call_instrumentation(state, codelike, offset, args, 3, | ||
| PY_MONITORING_EVENT_LINE); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
According to the documentation, the LINE event listeners only receive two arguments, not three.
https://docs.python.org/3.13/library/sys.monitoring.html#callback-function-arguments
Sorry, something went wrong.
There was an error while loading. Please reload this page.
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.