• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef Py_INTERNAL_CROSSINTERP_H
2 #define Py_INTERNAL_CROSSINTERP_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6 
7 #ifndef Py_BUILD_CORE
8 #  error "this header requires Py_BUILD_CORE define"
9 #endif
10 
11 #include "pycore_lock.h"            // PyMutex
12 #include "pycore_pyerrors.h"
13 
14 /**************/
15 /* exceptions */
16 /**************/
17 
18 PyAPI_DATA(PyObject *) PyExc_InterpreterError;
19 PyAPI_DATA(PyObject *) PyExc_InterpreterNotFoundError;
20 
21 
22 /***************************/
23 /* cross-interpreter calls */
24 /***************************/
25 
26 typedef int (*_Py_simple_func)(void *);
27 extern int _Py_CallInInterpreter(
28     PyInterpreterState *interp,
29     _Py_simple_func func,
30     void *arg);
31 extern int _Py_CallInInterpreterAndRawFree(
32     PyInterpreterState *interp,
33     _Py_simple_func func,
34     void *arg);
35 
36 
37 /**************************/
38 /* cross-interpreter data */
39 /**************************/
40 
41 typedef struct _xid _PyCrossInterpreterData;
42 typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *);
43 typedef void (*xid_freefunc)(void *);
44 
45 // _PyCrossInterpreterData is similar to Py_buffer as an effectively
46 // opaque struct that holds data outside the object machinery.  This
47 // is necessary to pass safely between interpreters in the same process.
48 struct _xid {
49     // data is the cross-interpreter-safe derivation of a Python object
50     // (see _PyObject_GetCrossInterpreterData).  It will be NULL if the
51     // new_object func (below) encodes the data.
52     void *data;
53     // obj is the Python object from which the data was derived.  This
54     // is non-NULL only if the data remains bound to the object in some
55     // way, such that the object must be "released" (via a decref) when
56     // the data is released.  In that case the code that sets the field,
57     // likely a registered "crossinterpdatafunc", is responsible for
58     // ensuring it owns the reference (i.e. incref).
59     PyObject *obj;
60     // interp is the ID of the owning interpreter of the original
61     // object.  It corresponds to the active interpreter when
62     // _PyObject_GetCrossInterpreterData() was called.  This should only
63     // be set by the cross-interpreter machinery.
64     //
65     // We use the ID rather than the PyInterpreterState to avoid issues
66     // with deleted interpreters.  Note that IDs are never re-used, so
67     // each one will always correspond to a specific interpreter
68     // (whether still alive or not).
69     int64_t interpid;
70     // new_object is a function that returns a new object in the current
71     // interpreter given the data.  The resulting object (a new
72     // reference) will be equivalent to the original object.  This field
73     // is required.
74     xid_newobjectfunc new_object;
75     // free is called when the data is released.  If it is NULL then
76     // nothing will be done to free the data.  For some types this is
77     // okay (e.g. bytes) and for those types this field should be set
78     // to NULL.  However, for most the data was allocated just for
79     // cross-interpreter use, so it must be freed when
80     // _PyCrossInterpreterData_Release is called or the memory will
81     // leak.  In that case, at the very least this field should be set
82     // to PyMem_RawFree (the default if not explicitly set to NULL).
83     // The call will happen with the original interpreter activated.
84     xid_freefunc free;
85 };
86 
87 PyAPI_FUNC(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void);
88 PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *data);
89 
90 #define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data)
91 #define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj)
92 #define _PyCrossInterpreterData_INTERPID(DATA) ((DATA)->interpid)
93 // Users should not need getters for "new_object" or "free".
94 
95 
96 /* defining cross-interpreter data */
97 
98 PyAPI_FUNC(void) _PyCrossInterpreterData_Init(
99         _PyCrossInterpreterData *data,
100         PyInterpreterState *interp, void *shared, PyObject *obj,
101         xid_newobjectfunc new_object);
102 PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize(
103         _PyCrossInterpreterData *,
104         PyInterpreterState *interp, const size_t, PyObject *,
105         xid_newobjectfunc);
106 PyAPI_FUNC(void) _PyCrossInterpreterData_Clear(
107         PyInterpreterState *, _PyCrossInterpreterData *);
108 
109 // Normally the Init* functions are sufficient.  The only time
110 // additional initialization might be needed is to set the "free" func,
111 // though that should be infrequent.
112 #define _PyCrossInterpreterData_SET_FREE(DATA, FUNC) \
113     do { \
114         (DATA)->free = (FUNC); \
115     } while (0)
116 // Additionally, some shareable types are essentially light wrappers
117 // around other shareable types.  The crossinterpdatafunc of the wrapper
118 // can often be implemented by calling the wrapped object's
119 // crossinterpdatafunc and then changing the "new_object" function.
120 // We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that,
121 // but might be better to have a function like
122 // _PyCrossInterpreterData_AdaptToWrapper() instead.
123 #define _PyCrossInterpreterData_SET_NEW_OBJECT(DATA, FUNC) \
124     do { \
125         (DATA)->new_object = (FUNC); \
126     } while (0)
127 
128 
129 /* using cross-interpreter data */
130 
131 PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *);
132 PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *);
133 PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *);
134 PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *);
135 PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *);
136 
137 
138 /* cross-interpreter data registry */
139 
140 // For now we use a global registry of shareable classes.  An
141 // alternative would be to add a tp_* slot for a class's
142 // crossinterpdatafunc. It would be simpler and more efficient.
143 
144 typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *,
145                                    _PyCrossInterpreterData *);
146 
147 struct _xidregitem;
148 
149 struct _xidregitem {
150     struct _xidregitem *prev;
151     struct _xidregitem *next;
152     /* This can be a dangling pointer, but only if weakref is set. */
153     PyTypeObject *cls;
154     /* This is NULL for builtin types. */
155     PyObject *weakref;
156     size_t refcount;
157     crossinterpdatafunc getdata;
158 };
159 
160 struct _xidregistry {
161     int global;  /* builtin types or heap types */
162     int initialized;
163     PyMutex mutex;
164     struct _xidregitem *head;
165 };
166 
167 PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc);
168 PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *);
169 PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *);
170 
171 
172 /*****************************/
173 /* runtime state & lifecycle */
174 /*****************************/
175 
176 struct _xi_runtime_state {
177     // builtin types
178     // XXX Remove this field once we have a tp_* slot.
179     struct _xidregistry registry;
180 };
181 
182 struct _xi_state {
183     // heap types
184     // XXX Remove this field once we have a tp_* slot.
185     struct _xidregistry registry;
186 
187     // heap types
188     PyObject *PyExc_NotShareableError;
189 };
190 
191 extern PyStatus _PyXI_Init(PyInterpreterState *interp);
192 extern void _PyXI_Fini(PyInterpreterState *interp);
193 
194 extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp);
195 extern void _PyXI_FiniTypes(PyInterpreterState *interp);
196 
197 #define _PyInterpreterState_GetXIState(interp) (&(interp)->xi)
198 
199 
200 /***************************/
201 /* short-term data sharing */
202 /***************************/
203 
204 // Ultimately we'd like to preserve enough information about the
205 // exception and traceback that we could re-constitute (or at least
206 // simulate, a la traceback.TracebackException), and even chain, a copy
207 // of the exception in the calling interpreter.
208 
209 typedef struct _excinfo {
210     struct _excinfo_type {
211         PyTypeObject *builtin;
212         const char *name;
213         const char *qualname;
214         const char *module;
215     } type;
216     const char *msg;
217     const char *errdisplay;
218 } _PyXI_excinfo;
219 
220 PyAPI_FUNC(int) _PyXI_InitExcInfo(_PyXI_excinfo *info, PyObject *exc);
221 PyAPI_FUNC(PyObject *) _PyXI_FormatExcInfo(_PyXI_excinfo *info);
222 PyAPI_FUNC(PyObject *) _PyXI_ExcInfoAsObject(_PyXI_excinfo *info);
223 PyAPI_FUNC(void) _PyXI_ClearExcInfo(_PyXI_excinfo *info);
224 
225 
226 typedef enum error_code {
227     _PyXI_ERR_NO_ERROR = 0,
228     _PyXI_ERR_UNCAUGHT_EXCEPTION = -1,
229     _PyXI_ERR_OTHER = -2,
230     _PyXI_ERR_NO_MEMORY = -3,
231     _PyXI_ERR_ALREADY_RUNNING = -4,
232     _PyXI_ERR_MAIN_NS_FAILURE = -5,
233     _PyXI_ERR_APPLY_NS_FAILURE = -6,
234     _PyXI_ERR_NOT_SHAREABLE = -7,
235 } _PyXI_errcode;
236 
237 
238 typedef struct _sharedexception {
239     // The originating interpreter.
240     PyInterpreterState *interp;
241     // The kind of error to propagate.
242     _PyXI_errcode code;
243     // The exception information to propagate, if applicable.
244     // This is populated only for some error codes,
245     // but always for _PyXI_ERR_UNCAUGHT_EXCEPTION.
246     _PyXI_excinfo uncaught;
247 } _PyXI_error;
248 
249 PyAPI_FUNC(PyObject *) _PyXI_ApplyError(_PyXI_error *err);
250 
251 
252 typedef struct xi_session _PyXI_session;
253 typedef struct _sharedns _PyXI_namespace;
254 
255 PyAPI_FUNC(void) _PyXI_FreeNamespace(_PyXI_namespace *ns);
256 PyAPI_FUNC(_PyXI_namespace *) _PyXI_NamespaceFromNames(PyObject *names);
257 PyAPI_FUNC(int) _PyXI_FillNamespaceFromDict(
258     _PyXI_namespace *ns,
259     PyObject *nsobj,
260     _PyXI_session *session);
261 PyAPI_FUNC(int) _PyXI_ApplyNamespace(
262     _PyXI_namespace *ns,
263     PyObject *nsobj,
264     PyObject *dflt);
265 
266 
267 // A cross-interpreter session involves entering an interpreter
268 // (_PyXI_Enter()), doing some work with it, and finally exiting
269 // that interpreter (_PyXI_Exit()).
270 //
271 // At the boundaries of the session, both entering and exiting,
272 // data may be exchanged between the previous interpreter and the
273 // target one in a thread-safe way that does not violate the
274 // isolation between interpreters.  This includes setting objects
275 // in the target's __main__ module on the way in, and capturing
276 // uncaught exceptions on the way out.
277 struct xi_session {
278     // Once a session has been entered, this is the tstate that was
279     // current before the session.  If it is different from cur_tstate
280     // then we must have switched interpreters.  Either way, this will
281     // be the current tstate once we exit the session.
282     PyThreadState *prev_tstate;
283     // Once a session has been entered, this is the current tstate.
284     // It must be current when the session exits.
285     PyThreadState *init_tstate;
286     // This is true if init_tstate needs cleanup during exit.
287     int own_init_tstate;
288 
289     // This is true if, while entering the session, init_thread took
290     // "ownership" of the interpreter's __main__ module.  This means
291     // it is the only thread that is allowed to run code there.
292     // (Caveat: for now, users may still run exec() against the
293     // __main__ module's dict, though that isn't advisable.)
294     int running;
295     // This is a cached reference to the __dict__ of the entered
296     // interpreter's __main__ module.  It is looked up when at the
297     // beginning of the session as a convenience.
298     PyObject *main_ns;
299 
300     // This is set if the interpreter is entered and raised an exception
301     // that needs to be handled in some special way during exit.
302     _PyXI_errcode *error_override;
303     // This is set if exit captured an exception to propagate.
304     _PyXI_error *error;
305 
306     // -- pre-allocated memory --
307     _PyXI_error _error;
308     _PyXI_errcode _error_override;
309 };
310 
311 PyAPI_FUNC(int) _PyXI_Enter(
312     _PyXI_session *session,
313     PyInterpreterState *interp,
314     PyObject *nsupdates);
315 PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session);
316 
317 PyAPI_FUNC(PyObject *) _PyXI_ApplyCapturedException(_PyXI_session *session);
318 PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session);
319 
320 
321 /*************/
322 /* other API */
323 /*************/
324 
325 // Export for _testinternalcapi shared extension
326 PyAPI_FUNC(PyInterpreterState *) _PyXI_NewInterpreter(
327     PyInterpreterConfig *config,
328     long *maybe_whence,
329     PyThreadState **p_tstate,
330     PyThreadState **p_save_tstate);
331 PyAPI_FUNC(void) _PyXI_EndInterpreter(
332     PyInterpreterState *interp,
333     PyThreadState *tstate,
334     PyThreadState **p_save_tstate);
335 
336 
337 #ifdef __cplusplus
338 }
339 #endif
340 #endif /* !Py_INTERNAL_CROSSINTERP_H */
341