77#include "pycore_ceval.h" // export _PyEval_SetProfile()
88#include "pycore_frame.h" // PyFrameObject members
99#include "pycore_interpframe.h" // _PyFrame_GetCode()
10+ #include "pycore_instruments.h" // PyUnstable_SetEvalCallback
1011
1112#include "opcode.h"
1213#include <stddef.h>
@@ -521,6 +522,39 @@ set_monitoring_profile_events(PyInterpreterState *interp)
521522 return _PyMonitoring_SetEvents (PY_MONITORING_SYS_PROFILE_ID , events );
522523}
523524
525+ int
526+ PyUnstable_SetEvalCallback (PyUnstable_EvalCallback callback , void * data )
527+ {
528+ PyInterpreterState * interp = _PyInterpreterState_GET ();
529+ interp -> eval_callback .callback = callback ;
530+ interp -> eval_callback .data = data ;
531+ return 0 ;
532+ }
533+
534+ PyUnstable_EvalCallback
535+ PyUnstable_GetEvalCallback (void * * data )
536+ {
537+ PyInterpreterState * interp = _PyInterpreterState_GET ();
538+ if (data != NULL ) {
539+ * data = interp -> eval_callback .data ;
540+ }
541+ return interp -> eval_callback .callback ;
542+ }
543+
544+ static inline void
545+ notify_eval_callback (PyInterpreterState * interp , PyUnstable_EvalEvent event )
546+ {
547+ if (interp -> eval_callback .callback != NULL ) {
548+ void * data = interp -> eval_callback .data ;
549+ if (interp -> eval_callback .callback (event , data ) < 0 ) {
550+ PyErr_FormatUnraisable (
551+ "Exception ignored in %s eval callback" ,
552+ (event == PyUnstable_EVAL_TRACE_SET || event == PyUnstable_EVAL_TRACE_CLEAR )
553+ ? "trace" : "profile" );
554+ }
555+ }
556+ }
557+
524558int
525559_PyEval_SetProfile (PyThreadState * tstate , Py_tracefunc func , PyObject * arg )
526560{
@@ -546,6 +580,10 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
546580 int ret = set_monitoring_profile_events (interp );
547581 _PyEval_StartTheWorld (interp );
548582 Py_XDECREF (old_profileobj ); // needs to be decref'd outside of stop-the-world
583+
584+ PyUnstable_EvalEvent event = (func != NULL ) ? PyUnstable_EVAL_PROFILE_SET : PyUnstable_EVAL_PROFILE_CLEAR ;
585+ notify_eval_callback (interp , event );
586+
549587 return ret ;
550588}
551589
@@ -586,6 +624,10 @@ _PyEval_SetProfileAllThreads(PyInterpreterState *interp, Py_tracefunc func, PyOb
586624 int ret = set_monitoring_profile_events (interp );
587625 _PyEval_StartTheWorld (interp );
588626 Py_XDECREF (old_profileobjs ); // needs to be decref'd outside of stop-the-world
627+
628+ PyUnstable_EvalEvent event = (func != NULL ) ? PyUnstable_EVAL_PROFILE_SET : PyUnstable_EVAL_PROFILE_CLEAR ;
629+ notify_eval_callback (interp , event );
630+
589631 return ret ;
590632}
591633
@@ -719,6 +761,10 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
719761done :
720762 _PyEval_StartTheWorld (interp );
721763 Py_XDECREF (old_traceobj ); // needs to be decref'd outside stop-the-world
764+
765+ PyUnstable_EvalEvent event = (func != NULL ) ? PyUnstable_EVAL_TRACE_SET : PyUnstable_EVAL_TRACE_CLEAR ;
766+ notify_eval_callback (interp , event );
767+
722768 return err ;
723769}
724770
@@ -770,5 +816,9 @@ _PyEval_SetTraceAllThreads(PyInterpreterState *interp, Py_tracefunc func, PyObje
770816 int err = set_monitoring_trace_events (interp );
771817 _PyEval_StartTheWorld (interp );
772818 Py_XDECREF (old_trace_objs ); // needs to be decref'd outside of stop-the-world
819+
820+ PyUnstable_EvalEvent event = (func != NULL ) ? PyUnstable_EVAL_TRACE_SET : PyUnstable_EVAL_TRACE_CLEAR ;
821+ notify_eval_callback (interp , event );
822+
773823 return err ;
774824}
0 commit comments