• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* API for managing interactions between isolated interpreters */
3 
4 #include "Python.h"
5 #include "pycore_ceval.h"         // _Py_simple_func
6 #include "pycore_crossinterp.h"   // struct _xid
7 #include "pycore_initconfig.h"    // _PyStatus_OK()
8 #include "pycore_namespace.h"     //_PyNamespace_New()
9 #include "pycore_pyerrors.h"      // _PyErr_Clear()
10 #include "pycore_weakref.h"       // _PyWeakref_GET_REF()
11 
12 
13 /**************/
14 /* exceptions */
15 /**************/
16 
17 static int init_exceptions(PyInterpreterState *);
18 static void fini_exceptions(PyInterpreterState *);
19 static int _init_not_shareable_error_type(PyInterpreterState *);
20 static void _fini_not_shareable_error_type(PyInterpreterState *);
21 static PyObject * _get_not_shareable_error_type(PyInterpreterState *);
22 #include "crossinterp_exceptions.h"
23 
24 
25 /***************************/
26 /* cross-interpreter calls */
27 /***************************/
28 
29 int
_Py_CallInInterpreter(PyInterpreterState * interp,_Py_simple_func func,void * arg)30 _Py_CallInInterpreter(PyInterpreterState *interp,
31                       _Py_simple_func func, void *arg)
32 {
33     if (interp == PyInterpreterState_Get()) {
34         return func(arg);
35     }
36     // XXX Emit a warning if this fails?
37     _PyEval_AddPendingCall(interp, (_Py_pending_call_func)func, arg, 0);
38     return 0;
39 }
40 
41 int
_Py_CallInInterpreterAndRawFree(PyInterpreterState * interp,_Py_simple_func func,void * arg)42 _Py_CallInInterpreterAndRawFree(PyInterpreterState *interp,
43                                 _Py_simple_func func, void *arg)
44 {
45     if (interp == PyInterpreterState_Get()) {
46         int res = func(arg);
47         PyMem_RawFree(arg);
48         return res;
49     }
50     // XXX Emit a warning if this fails?
51     _PyEval_AddPendingCall(interp, func, arg, _Py_PENDING_RAWFREE);
52     return 0;
53 }
54 
55 
56 /**************************/
57 /* cross-interpreter data */
58 /**************************/
59 
60 /* registry of {type -> crossinterpdatafunc} */
61 
62 /* For now we use a global registry of shareable classes.  An
63    alternative would be to add a tp_* slot for a class's
64    crossinterpdatafunc. It would be simpler and more efficient. */
65 
66 static void xid_lookup_init(PyInterpreterState *);
67 static void xid_lookup_fini(PyInterpreterState *);
68 static crossinterpdatafunc lookup_getdata(PyInterpreterState *, PyObject *);
69 #include "crossinterp_data_lookup.h"
70 
71 
72 /* lifecycle */
73 
74 _PyCrossInterpreterData *
_PyCrossInterpreterData_New(void)75 _PyCrossInterpreterData_New(void)
76 {
77     _PyCrossInterpreterData *xid = PyMem_RawMalloc(
78                                             sizeof(_PyCrossInterpreterData));
79     if (xid == NULL) {
80         PyErr_NoMemory();
81     }
82     return xid;
83 }
84 
85 void
_PyCrossInterpreterData_Free(_PyCrossInterpreterData * xid)86 _PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid)
87 {
88     PyInterpreterState *interp = PyInterpreterState_Get();
89     _PyCrossInterpreterData_Clear(interp, xid);
90     PyMem_RawFree(xid);
91 }
92 
93 
94 /* defining cross-interpreter data */
95 
96 static inline void
_xidata_init(_PyCrossInterpreterData * data)97 _xidata_init(_PyCrossInterpreterData *data)
98 {
99     // If the value is being reused
100     // then _xidata_clear() should have been called already.
101     assert(data->data == NULL);
102     assert(data->obj == NULL);
103     *data = (_PyCrossInterpreterData){0};
104     _PyCrossInterpreterData_INTERPID(data) = -1;
105 }
106 
107 static inline void
_xidata_clear(_PyCrossInterpreterData * data)108 _xidata_clear(_PyCrossInterpreterData *data)
109 {
110     // _PyCrossInterpreterData only has two members that need to be
111     // cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
112     // In both cases the original (owning) interpreter must be used,
113     // which is the caller's responsibility to ensure.
114     if (data->data != NULL) {
115         if (data->free != NULL) {
116             data->free(data->data);
117         }
118         data->data = NULL;
119     }
120     Py_CLEAR(data->obj);
121 }
122 
123 void
_PyCrossInterpreterData_Init(_PyCrossInterpreterData * data,PyInterpreterState * interp,void * shared,PyObject * obj,xid_newobjectfunc new_object)124 _PyCrossInterpreterData_Init(_PyCrossInterpreterData *data,
125                              PyInterpreterState *interp,
126                              void *shared, PyObject *obj,
127                              xid_newobjectfunc new_object)
128 {
129     assert(data != NULL);
130     assert(new_object != NULL);
131     _xidata_init(data);
132     data->data = shared;
133     if (obj != NULL) {
134         assert(interp != NULL);
135         // released in _PyCrossInterpreterData_Clear()
136         data->obj = Py_NewRef(obj);
137     }
138     // Ideally every object would know its owning interpreter.
139     // Until then, we have to rely on the caller to identify it
140     // (but we don't need it in all cases).
141     _PyCrossInterpreterData_INTERPID(data) = (interp != NULL)
142         ? PyInterpreterState_GetID(interp)
143         : -1;
144     data->new_object = new_object;
145 }
146 
147 int
_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData * data,PyInterpreterState * interp,const size_t size,PyObject * obj,xid_newobjectfunc new_object)148 _PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data,
149                                      PyInterpreterState *interp,
150                                      const size_t size, PyObject *obj,
151                                      xid_newobjectfunc new_object)
152 {
153     assert(size > 0);
154     // For now we always free the shared data in the same interpreter
155     // where it was allocated, so the interpreter is required.
156     assert(interp != NULL);
157     _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object);
158     data->data = PyMem_RawMalloc(size);
159     if (data->data == NULL) {
160         return -1;
161     }
162     data->free = PyMem_RawFree;
163     return 0;
164 }
165 
166 void
_PyCrossInterpreterData_Clear(PyInterpreterState * interp,_PyCrossInterpreterData * data)167 _PyCrossInterpreterData_Clear(PyInterpreterState *interp,
168                               _PyCrossInterpreterData *data)
169 {
170     assert(data != NULL);
171     // This must be called in the owning interpreter.
172     assert(interp == NULL
173            || _PyCrossInterpreterData_INTERPID(data) == -1
174            || _PyCrossInterpreterData_INTERPID(data) == PyInterpreterState_GetID(interp));
175     _xidata_clear(data);
176 }
177 
178 
179 /* using cross-interpreter data */
180 
181 static int
_check_xidata(PyThreadState * tstate,_PyCrossInterpreterData * data)182 _check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data)
183 {
184     // data->data can be anything, including NULL, so we don't check it.
185 
186     // data->obj may be NULL, so we don't check it.
187 
188     if (_PyCrossInterpreterData_INTERPID(data) < 0) {
189         PyErr_SetString(PyExc_SystemError, "missing interp");
190         return -1;
191     }
192 
193     if (data->new_object == NULL) {
194         PyErr_SetString(PyExc_SystemError, "missing new_object func");
195         return -1;
196     }
197 
198     // data->free may be NULL, so we don't check it.
199 
200     return 0;
201 }
202 
203 static inline void
_set_xid_lookup_failure(PyInterpreterState * interp,PyObject * obj,const char * msg)204 _set_xid_lookup_failure(PyInterpreterState *interp,
205                         PyObject *obj, const char *msg)
206 {
207     PyObject *exctype = _get_not_shareable_error_type(interp);
208     assert(exctype != NULL);
209     if (msg != NULL) {
210         assert(obj == NULL);
211         PyErr_SetString(exctype, msg);
212     }
213     else if (obj == NULL) {
214         PyErr_SetString(exctype,
215                         "object does not support cross-interpreter data");
216     }
217     else {
218         PyErr_Format(exctype,
219                      "%S does not support cross-interpreter data", obj);
220     }
221 }
222 
223 int
_PyObject_CheckCrossInterpreterData(PyObject * obj)224 _PyObject_CheckCrossInterpreterData(PyObject *obj)
225 {
226     PyInterpreterState *interp = PyInterpreterState_Get();
227     crossinterpdatafunc getdata = lookup_getdata(interp, obj);
228     if (getdata == NULL) {
229         if (!PyErr_Occurred()) {
230             _set_xid_lookup_failure(interp, obj, NULL);
231         }
232         return -1;
233     }
234     return 0;
235 }
236 
237 int
_PyObject_GetCrossInterpreterData(PyObject * obj,_PyCrossInterpreterData * data)238 _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
239 {
240     PyThreadState *tstate = PyThreadState_Get();
241     PyInterpreterState *interp = tstate->interp;
242 
243     // Reset data before re-populating.
244     *data = (_PyCrossInterpreterData){0};
245     _PyCrossInterpreterData_INTERPID(data) = -1;
246 
247     // Call the "getdata" func for the object.
248     Py_INCREF(obj);
249     crossinterpdatafunc getdata = lookup_getdata(interp, obj);
250     if (getdata == NULL) {
251         Py_DECREF(obj);
252         if (!PyErr_Occurred()) {
253             _set_xid_lookup_failure(interp, obj, NULL);
254         }
255         return -1;
256     }
257     int res = getdata(tstate, obj, data);
258     Py_DECREF(obj);
259     if (res != 0) {
260         return -1;
261     }
262 
263     // Fill in the blanks and validate the result.
264     _PyCrossInterpreterData_INTERPID(data) = PyInterpreterState_GetID(interp);
265     if (_check_xidata(tstate, data) != 0) {
266         (void)_PyCrossInterpreterData_Release(data);
267         return -1;
268     }
269 
270     return 0;
271 }
272 
273 PyObject *
_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData * data)274 _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
275 {
276     return data->new_object(data);
277 }
278 
279 static int
_call_clear_xidata(void * data)280 _call_clear_xidata(void *data)
281 {
282     _xidata_clear((_PyCrossInterpreterData *)data);
283     return 0;
284 }
285 
286 static int
_xidata_release(_PyCrossInterpreterData * data,int rawfree)287 _xidata_release(_PyCrossInterpreterData *data, int rawfree)
288 {
289     if ((data->data == NULL || data->free == NULL) && data->obj == NULL) {
290         // Nothing to release!
291         if (rawfree) {
292             PyMem_RawFree(data);
293         }
294         else {
295             data->data = NULL;
296         }
297         return 0;
298     }
299 
300     // Switch to the original interpreter.
301     PyInterpreterState *interp = _PyInterpreterState_LookUpID(
302                                     _PyCrossInterpreterData_INTERPID(data));
303     if (interp == NULL) {
304         // The interpreter was already destroyed.
305         // This function shouldn't have been called.
306         // XXX Someone leaked some memory...
307         assert(PyErr_Occurred());
308         if (rawfree) {
309             PyMem_RawFree(data);
310         }
311         return -1;
312     }
313 
314     // "Release" the data and/or the object.
315     if (rawfree) {
316         return _Py_CallInInterpreterAndRawFree(interp, _call_clear_xidata, data);
317     }
318     else {
319         return _Py_CallInInterpreter(interp, _call_clear_xidata, data);
320     }
321 }
322 
323 int
_PyCrossInterpreterData_Release(_PyCrossInterpreterData * data)324 _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
325 {
326     return _xidata_release(data, 0);
327 }
328 
329 int
_PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData * data)330 _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *data)
331 {
332     return _xidata_release(data, 1);
333 }
334 
335 
336 /*************************/
337 /* convenience utilities */
338 /*************************/
339 
340 static const char *
_copy_string_obj_raw(PyObject * strobj,Py_ssize_t * p_size)341 _copy_string_obj_raw(PyObject *strobj, Py_ssize_t *p_size)
342 {
343     Py_ssize_t size = -1;
344     const char *str = PyUnicode_AsUTF8AndSize(strobj, &size);
345     if (str == NULL) {
346         return NULL;
347     }
348 
349     if (size != (Py_ssize_t)strlen(str)) {
350         PyErr_SetString(PyExc_ValueError, "found embedded NULL character");
351         return NULL;
352     }
353 
354     char *copied = PyMem_RawMalloc(size+1);
355     if (copied == NULL) {
356         PyErr_NoMemory();
357         return NULL;
358     }
359     strcpy(copied, str);
360     if (p_size != NULL) {
361         *p_size = size;
362     }
363     return copied;
364 }
365 
366 
367 static int
_convert_exc_to_TracebackException(PyObject * exc,PyObject ** p_tbexc)368 _convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc)
369 {
370     PyObject *args = NULL;
371     PyObject *kwargs = NULL;
372     PyObject *create = NULL;
373 
374     // This is inspired by _PyErr_Display().
375     PyObject *tbmod = PyImport_ImportModule("traceback");
376     if (tbmod == NULL) {
377         return -1;
378     }
379     PyObject *tbexc_type = PyObject_GetAttrString(tbmod, "TracebackException");
380     Py_DECREF(tbmod);
381     if (tbexc_type == NULL) {
382         return -1;
383     }
384     create = PyObject_GetAttrString(tbexc_type, "from_exception");
385     Py_DECREF(tbexc_type);
386     if (create == NULL) {
387         return -1;
388     }
389 
390     args = PyTuple_Pack(1, exc);
391     if (args == NULL) {
392         goto error;
393     }
394 
395     kwargs = PyDict_New();
396     if (kwargs == NULL) {
397         goto error;
398     }
399     if (PyDict_SetItemString(kwargs, "save_exc_type", Py_False) < 0) {
400         goto error;
401     }
402     if (PyDict_SetItemString(kwargs, "lookup_lines", Py_False) < 0) {
403         goto error;
404     }
405 
406     PyObject *tbexc = PyObject_Call(create, args, kwargs);
407     Py_DECREF(args);
408     Py_DECREF(kwargs);
409     Py_DECREF(create);
410     if (tbexc == NULL) {
411         goto error;
412     }
413 
414     *p_tbexc = tbexc;
415     return 0;
416 
417 error:
418     Py_XDECREF(args);
419     Py_XDECREF(kwargs);
420     Py_XDECREF(create);
421     return -1;
422 }
423 
424 // We accommodate backports here.
425 #ifndef _Py_EMPTY_STR
426 # define _Py_EMPTY_STR &_Py_STR(empty)
427 #endif
428 
429 static const char *
_format_TracebackException(PyObject * tbexc)430 _format_TracebackException(PyObject *tbexc)
431 {
432     PyObject *lines = PyObject_CallMethod(tbexc, "format", NULL);
433     if (lines == NULL) {
434         return NULL;
435     }
436     assert(_Py_EMPTY_STR != NULL);
437     PyObject *formatted_obj = PyUnicode_Join(_Py_EMPTY_STR, lines);
438     Py_DECREF(lines);
439     if (formatted_obj == NULL) {
440         return NULL;
441     }
442 
443     Py_ssize_t size = -1;
444     const char *formatted = _copy_string_obj_raw(formatted_obj, &size);
445     Py_DECREF(formatted_obj);
446     // We remove trailing the newline added by TracebackException.format().
447     assert(formatted[size-1] == '\n');
448     ((char *)formatted)[size-1] = '\0';
449     return formatted;
450 }
451 
452 
453 static int
_release_xid_data(_PyCrossInterpreterData * data,int rawfree)454 _release_xid_data(_PyCrossInterpreterData *data, int rawfree)
455 {
456     PyObject *exc = PyErr_GetRaisedException();
457     int res = rawfree
458         ? _PyCrossInterpreterData_Release(data)
459         : _PyCrossInterpreterData_ReleaseAndRawFree(data);
460     if (res < 0) {
461         /* The owning interpreter is already destroyed. */
462         _PyCrossInterpreterData_Clear(NULL, data);
463         // XXX Emit a warning?
464         PyErr_Clear();
465     }
466     PyErr_SetRaisedException(exc);
467     return res;
468 }
469 
470 
471 /***********************/
472 /* exception snapshots */
473 /***********************/
474 
475 static int
_excinfo_init_type_from_exception(struct _excinfo_type * info,PyObject * exc)476 _excinfo_init_type_from_exception(struct _excinfo_type *info, PyObject *exc)
477 {
478     /* Note that this copies directly rather than into an intermediate
479        struct and does not clear on error.  If we need that then we
480        should have a separate function to wrap this one
481        and do all that there. */
482     PyObject *strobj = NULL;
483 
484     PyTypeObject *type = Py_TYPE(exc);
485     if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
486         assert(_Py_IsImmortal((PyObject *)type));
487         info->builtin = type;
488     }
489     else {
490         // Only builtin types are preserved.
491         info->builtin = NULL;
492     }
493 
494     // __name__
495     strobj = PyType_GetName(type);
496     if (strobj == NULL) {
497         return -1;
498     }
499     info->name = _copy_string_obj_raw(strobj, NULL);
500     Py_DECREF(strobj);
501     if (info->name == NULL) {
502         return -1;
503     }
504 
505     // __qualname__
506     strobj = PyType_GetQualName(type);
507     if (strobj == NULL) {
508         return -1;
509     }
510     info->qualname = _copy_string_obj_raw(strobj, NULL);
511     Py_DECREF(strobj);
512     if (info->qualname == NULL) {
513         return -1;
514     }
515 
516     // __module__
517     strobj = PyType_GetModuleName(type);
518     if (strobj == NULL) {
519         return -1;
520     }
521     info->module = _copy_string_obj_raw(strobj, NULL);
522     Py_DECREF(strobj);
523     if (info->module == NULL) {
524         return -1;
525     }
526 
527     return 0;
528 }
529 
530 static int
_excinfo_init_type_from_object(struct _excinfo_type * info,PyObject * exctype)531 _excinfo_init_type_from_object(struct _excinfo_type *info, PyObject *exctype)
532 {
533     PyObject *strobj = NULL;
534 
535     // __name__
536     strobj = PyObject_GetAttrString(exctype, "__name__");
537     if (strobj == NULL) {
538         return -1;
539     }
540     info->name = _copy_string_obj_raw(strobj, NULL);
541     Py_DECREF(strobj);
542     if (info->name == NULL) {
543         return -1;
544     }
545 
546     // __qualname__
547     strobj = PyObject_GetAttrString(exctype, "__qualname__");
548     if (strobj == NULL) {
549         return -1;
550     }
551     info->qualname = _copy_string_obj_raw(strobj, NULL);
552     Py_DECREF(strobj);
553     if (info->qualname == NULL) {
554         return -1;
555     }
556 
557     // __module__
558     strobj = PyObject_GetAttrString(exctype, "__module__");
559     if (strobj == NULL) {
560         return -1;
561     }
562     info->module = _copy_string_obj_raw(strobj, NULL);
563     Py_DECREF(strobj);
564     if (info->module == NULL) {
565         return -1;
566     }
567 
568     return 0;
569 }
570 
571 static void
_excinfo_clear_type(struct _excinfo_type * info)572 _excinfo_clear_type(struct _excinfo_type *info)
573 {
574     if (info->builtin != NULL) {
575         assert(info->builtin->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
576         assert(_Py_IsImmortal((PyObject *)info->builtin));
577     }
578     if (info->name != NULL) {
579         PyMem_RawFree((void *)info->name);
580     }
581     if (info->qualname != NULL) {
582         PyMem_RawFree((void *)info->qualname);
583     }
584     if (info->module != NULL) {
585         PyMem_RawFree((void *)info->module);
586     }
587     *info = (struct _excinfo_type){NULL};
588 }
589 
590 static void
_excinfo_normalize_type(struct _excinfo_type * info,const char ** p_module,const char ** p_qualname)591 _excinfo_normalize_type(struct _excinfo_type *info,
592                         const char **p_module, const char **p_qualname)
593 {
594     if (info->name == NULL) {
595         assert(info->builtin == NULL);
596         assert(info->qualname == NULL);
597         assert(info->module == NULL);
598         // This is inspired by TracebackException.format_exception_only().
599         *p_module = NULL;
600         *p_qualname = NULL;
601         return;
602     }
603 
604     const char *module = info->module;
605     const char *qualname = info->qualname;
606     if (qualname == NULL) {
607         qualname = info->name;
608     }
609     assert(module != NULL);
610     if (strcmp(module, "builtins") == 0) {
611         module = NULL;
612     }
613     else if (strcmp(module, "__main__") == 0) {
614         module = NULL;
615     }
616     *p_qualname = qualname;
617     *p_module = module;
618 }
619 
620 static void
_PyXI_excinfo_Clear(_PyXI_excinfo * info)621 _PyXI_excinfo_Clear(_PyXI_excinfo *info)
622 {
623     _excinfo_clear_type(&info->type);
624     if (info->msg != NULL) {
625         PyMem_RawFree((void *)info->msg);
626     }
627     if (info->errdisplay != NULL) {
628         PyMem_RawFree((void *)info->errdisplay);
629     }
630     *info = (_PyXI_excinfo){{NULL}};
631 }
632 
633 PyObject *
_PyXI_excinfo_format(_PyXI_excinfo * info)634 _PyXI_excinfo_format(_PyXI_excinfo *info)
635 {
636     const char *module, *qualname;
637     _excinfo_normalize_type(&info->type, &module, &qualname);
638     if (qualname != NULL) {
639         if (module != NULL) {
640             if (info->msg != NULL) {
641                 return PyUnicode_FromFormat("%s.%s: %s",
642                                             module, qualname, info->msg);
643             }
644             else {
645                 return PyUnicode_FromFormat("%s.%s", module, qualname);
646             }
647         }
648         else {
649             if (info->msg != NULL) {
650                 return PyUnicode_FromFormat("%s: %s", qualname, info->msg);
651             }
652             else {
653                 return PyUnicode_FromString(qualname);
654             }
655         }
656     }
657     else if (info->msg != NULL) {
658         return PyUnicode_FromString(info->msg);
659     }
660     else {
661         Py_RETURN_NONE;
662     }
663 }
664 
665 static const char *
_PyXI_excinfo_InitFromException(_PyXI_excinfo * info,PyObject * exc)666 _PyXI_excinfo_InitFromException(_PyXI_excinfo *info, PyObject *exc)
667 {
668     assert(exc != NULL);
669 
670     if (PyErr_GivenExceptionMatches(exc, PyExc_MemoryError)) {
671         _PyXI_excinfo_Clear(info);
672         return NULL;
673     }
674     const char *failure = NULL;
675 
676     if (_excinfo_init_type_from_exception(&info->type, exc) < 0) {
677         failure = "error while initializing exception type snapshot";
678         goto error;
679     }
680 
681     // Extract the exception message.
682     PyObject *msgobj = PyObject_Str(exc);
683     if (msgobj == NULL) {
684         failure = "error while formatting exception";
685         goto error;
686     }
687     info->msg = _copy_string_obj_raw(msgobj, NULL);
688     Py_DECREF(msgobj);
689     if (info->msg == NULL) {
690         failure = "error while copying exception message";
691         goto error;
692     }
693 
694     // Pickle a traceback.TracebackException.
695     PyObject *tbexc = NULL;
696     if (_convert_exc_to_TracebackException(exc, &tbexc) < 0) {
697 #ifdef Py_DEBUG
698         PyErr_FormatUnraisable("Exception ignored while creating TracebackException");
699 #endif
700         PyErr_Clear();
701     }
702     else {
703         info->errdisplay = _format_TracebackException(tbexc);
704         Py_DECREF(tbexc);
705         if (info->errdisplay == NULL) {
706 #ifdef Py_DEBUG
707             PyErr_FormatUnraisable("Exception ignored while formatting TracebackException");
708 #endif
709             PyErr_Clear();
710         }
711     }
712 
713     return NULL;
714 
715 error:
716     assert(failure != NULL);
717     _PyXI_excinfo_Clear(info);
718     return failure;
719 }
720 
721 static const char *
_PyXI_excinfo_InitFromObject(_PyXI_excinfo * info,PyObject * obj)722 _PyXI_excinfo_InitFromObject(_PyXI_excinfo *info, PyObject *obj)
723 {
724     const char *failure = NULL;
725 
726     PyObject *exctype = PyObject_GetAttrString(obj, "type");
727     if (exctype == NULL) {
728         failure = "exception snapshot missing 'type' attribute";
729         goto error;
730     }
731     int res = _excinfo_init_type_from_object(&info->type, exctype);
732     Py_DECREF(exctype);
733     if (res < 0) {
734         failure = "error while initializing exception type snapshot";
735         goto error;
736     }
737 
738     // Extract the exception message.
739     PyObject *msgobj = PyObject_GetAttrString(obj, "msg");
740     if (msgobj == NULL) {
741         failure = "exception snapshot missing 'msg' attribute";
742         goto error;
743     }
744     info->msg = _copy_string_obj_raw(msgobj, NULL);
745     Py_DECREF(msgobj);
746     if (info->msg == NULL) {
747         failure = "error while copying exception message";
748         goto error;
749     }
750 
751     // Pickle a traceback.TracebackException.
752     PyObject *errdisplay = PyObject_GetAttrString(obj, "errdisplay");
753     if (errdisplay == NULL) {
754         failure = "exception snapshot missing 'errdisplay' attribute";
755         goto error;
756     }
757     info->errdisplay = _copy_string_obj_raw(errdisplay, NULL);
758     Py_DECREF(errdisplay);
759     if (info->errdisplay == NULL) {
760         failure = "error while copying exception error display";
761         goto error;
762     }
763 
764     return NULL;
765 
766 error:
767     assert(failure != NULL);
768     _PyXI_excinfo_Clear(info);
769     return failure;
770 }
771 
772 static void
_PyXI_excinfo_Apply(_PyXI_excinfo * info,PyObject * exctype)773 _PyXI_excinfo_Apply(_PyXI_excinfo *info, PyObject *exctype)
774 {
775     PyObject *tbexc = NULL;
776     if (info->errdisplay != NULL) {
777         tbexc = PyUnicode_FromString(info->errdisplay);
778         if (tbexc == NULL) {
779             PyErr_Clear();
780         }
781     }
782 
783     PyObject *formatted = _PyXI_excinfo_format(info);
784     PyErr_SetObject(exctype, formatted);
785     Py_DECREF(formatted);
786 
787     if (tbexc != NULL) {
788         PyObject *exc = PyErr_GetRaisedException();
789         if (PyObject_SetAttrString(exc, "_errdisplay", tbexc) < 0) {
790 #ifdef Py_DEBUG
791             PyErr_FormatUnraisable("Exception ignored when setting _errdisplay");
792 #endif
793             PyErr_Clear();
794         }
795         Py_DECREF(tbexc);
796         PyErr_SetRaisedException(exc);
797     }
798 }
799 
800 static PyObject *
_PyXI_excinfo_TypeAsObject(_PyXI_excinfo * info)801 _PyXI_excinfo_TypeAsObject(_PyXI_excinfo *info)
802 {
803     PyObject *ns = _PyNamespace_New(NULL);
804     if (ns == NULL) {
805         return NULL;
806     }
807     int empty = 1;
808 
809     if (info->type.name != NULL) {
810         PyObject *name = PyUnicode_FromString(info->type.name);
811         if (name == NULL) {
812             goto error;
813         }
814         int res = PyObject_SetAttrString(ns, "__name__", name);
815         Py_DECREF(name);
816         if (res < 0) {
817             goto error;
818         }
819         empty = 0;
820     }
821 
822     if (info->type.qualname != NULL) {
823         PyObject *qualname = PyUnicode_FromString(info->type.qualname);
824         if (qualname == NULL) {
825             goto error;
826         }
827         int res = PyObject_SetAttrString(ns, "__qualname__", qualname);
828         Py_DECREF(qualname);
829         if (res < 0) {
830             goto error;
831         }
832         empty = 0;
833     }
834 
835     if (info->type.module != NULL) {
836         PyObject *module = PyUnicode_FromString(info->type.module);
837         if (module == NULL) {
838             goto error;
839         }
840         int res = PyObject_SetAttrString(ns, "__module__", module);
841         Py_DECREF(module);
842         if (res < 0) {
843             goto error;
844         }
845         empty = 0;
846     }
847 
848     if (empty) {
849         Py_CLEAR(ns);
850     }
851 
852     return ns;
853 
854 error:
855     Py_DECREF(ns);
856     return NULL;
857 }
858 
859 static PyObject *
_PyXI_excinfo_AsObject(_PyXI_excinfo * info)860 _PyXI_excinfo_AsObject(_PyXI_excinfo *info)
861 {
862     PyObject *ns = _PyNamespace_New(NULL);
863     if (ns == NULL) {
864         return NULL;
865     }
866     int res;
867 
868     PyObject *type = _PyXI_excinfo_TypeAsObject(info);
869     if (type == NULL) {
870         if (PyErr_Occurred()) {
871             goto error;
872         }
873         type = Py_NewRef(Py_None);
874     }
875     res = PyObject_SetAttrString(ns, "type", type);
876     Py_DECREF(type);
877     if (res < 0) {
878         goto error;
879     }
880 
881     PyObject *msg = info->msg != NULL
882         ? PyUnicode_FromString(info->msg)
883         : Py_NewRef(Py_None);
884     if (msg == NULL) {
885         goto error;
886     }
887     res = PyObject_SetAttrString(ns, "msg", msg);
888     Py_DECREF(msg);
889     if (res < 0) {
890         goto error;
891     }
892 
893     PyObject *formatted = _PyXI_excinfo_format(info);
894     if (formatted == NULL) {
895         goto error;
896     }
897     res = PyObject_SetAttrString(ns, "formatted", formatted);
898     Py_DECREF(formatted);
899     if (res < 0) {
900         goto error;
901     }
902 
903     if (info->errdisplay != NULL) {
904         PyObject *tbexc = PyUnicode_FromString(info->errdisplay);
905         if (tbexc == NULL) {
906             PyErr_Clear();
907         }
908         else {
909             res = PyObject_SetAttrString(ns, "errdisplay", tbexc);
910             Py_DECREF(tbexc);
911             if (res < 0) {
912                 goto error;
913             }
914         }
915     }
916 
917     return ns;
918 
919 error:
920     Py_DECREF(ns);
921     return NULL;
922 }
923 
924 
925 int
_PyXI_InitExcInfo(_PyXI_excinfo * info,PyObject * exc)926 _PyXI_InitExcInfo(_PyXI_excinfo *info, PyObject *exc)
927 {
928     assert(!PyErr_Occurred());
929     if (exc == NULL || exc == Py_None) {
930         PyErr_SetString(PyExc_ValueError, "missing exc");
931         return -1;
932     }
933     const char *failure;
934     if (PyExceptionInstance_Check(exc) || PyExceptionClass_Check(exc)) {
935         failure = _PyXI_excinfo_InitFromException(info, exc);
936     }
937     else {
938         failure = _PyXI_excinfo_InitFromObject(info, exc);
939     }
940     if (failure != NULL) {
941         PyErr_SetString(PyExc_Exception, failure);
942         return -1;
943     }
944     return 0;
945 }
946 
947 PyObject *
_PyXI_FormatExcInfo(_PyXI_excinfo * info)948 _PyXI_FormatExcInfo(_PyXI_excinfo *info)
949 {
950     return _PyXI_excinfo_format(info);
951 }
952 
953 PyObject *
_PyXI_ExcInfoAsObject(_PyXI_excinfo * info)954 _PyXI_ExcInfoAsObject(_PyXI_excinfo *info)
955 {
956     return _PyXI_excinfo_AsObject(info);
957 }
958 
959 void
_PyXI_ClearExcInfo(_PyXI_excinfo * info)960 _PyXI_ClearExcInfo(_PyXI_excinfo *info)
961 {
962     _PyXI_excinfo_Clear(info);
963 }
964 
965 
966 /***************************/
967 /* short-term data sharing */
968 /***************************/
969 
970 /* error codes */
971 
972 static int
_PyXI_ApplyErrorCode(_PyXI_errcode code,PyInterpreterState * interp)973 _PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
974 {
975     assert(!PyErr_Occurred());
976     switch (code) {
977     case _PyXI_ERR_NO_ERROR:  // fall through
978     case _PyXI_ERR_UNCAUGHT_EXCEPTION:
979         // There is nothing to apply.
980 #ifdef Py_DEBUG
981         Py_UNREACHABLE();
982 #endif
983         return 0;
984     case _PyXI_ERR_OTHER:
985         // XXX msg?
986         PyErr_SetNone(PyExc_InterpreterError);
987         break;
988     case _PyXI_ERR_NO_MEMORY:
989         PyErr_NoMemory();
990         break;
991     case _PyXI_ERR_ALREADY_RUNNING:
992         assert(interp != NULL);
993         // In 3.14+ we use _PyErr_SetInterpreterAlreadyRunning().
994         PyErr_SetString(PyExc_InterpreterError, "interpreter already running");
995         break;
996     case _PyXI_ERR_MAIN_NS_FAILURE:
997         PyErr_SetString(PyExc_InterpreterError,
998                         "failed to get __main__ namespace");
999         break;
1000     case _PyXI_ERR_APPLY_NS_FAILURE:
1001         PyErr_SetString(PyExc_InterpreterError,
1002                         "failed to apply namespace to __main__");
1003         break;
1004     case _PyXI_ERR_NOT_SHAREABLE:
1005         _set_xid_lookup_failure(interp, NULL, NULL);
1006         break;
1007     default:
1008 #ifdef Py_DEBUG
1009         Py_UNREACHABLE();
1010 #else
1011         PyErr_Format(PyExc_RuntimeError, "unsupported error code %d", code);
1012 #endif
1013     }
1014     assert(PyErr_Occurred());
1015     return -1;
1016 }
1017 
1018 /* shared exceptions */
1019 
1020 static const char *
_PyXI_InitError(_PyXI_error * error,PyObject * excobj,_PyXI_errcode code)1021 _PyXI_InitError(_PyXI_error *error, PyObject *excobj, _PyXI_errcode code)
1022 {
1023     if (error->interp == NULL) {
1024         error->interp = PyInterpreterState_Get();
1025     }
1026 
1027     const char *failure = NULL;
1028     if (code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
1029         // There is an unhandled exception we need to propagate.
1030         failure = _PyXI_excinfo_InitFromException(&error->uncaught, excobj);
1031         if (failure != NULL) {
1032             // We failed to initialize error->uncaught.
1033             // XXX Print the excobj/traceback?  Emit a warning?
1034             // XXX Print the current exception/traceback?
1035             if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
1036                 error->code = _PyXI_ERR_NO_MEMORY;
1037             }
1038             else {
1039                 error->code = _PyXI_ERR_OTHER;
1040             }
1041             PyErr_Clear();
1042         }
1043         else {
1044             error->code = code;
1045         }
1046         assert(error->code != _PyXI_ERR_NO_ERROR);
1047     }
1048     else {
1049         // There is an error code we need to propagate.
1050         assert(excobj == NULL);
1051         assert(code != _PyXI_ERR_NO_ERROR);
1052         error->code = code;
1053         _PyXI_excinfo_Clear(&error->uncaught);
1054     }
1055     return failure;
1056 }
1057 
1058 PyObject *
_PyXI_ApplyError(_PyXI_error * error)1059 _PyXI_ApplyError(_PyXI_error *error)
1060 {
1061     if (error->code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
1062         // Raise an exception that proxies the propagated exception.
1063        return _PyXI_excinfo_AsObject(&error->uncaught);
1064     }
1065     else if (error->code == _PyXI_ERR_NOT_SHAREABLE) {
1066         // Propagate the exception directly.
1067         _set_xid_lookup_failure(error->interp, NULL, error->uncaught.msg);
1068     }
1069     else {
1070         // Raise an exception corresponding to the code.
1071         assert(error->code != _PyXI_ERR_NO_ERROR);
1072         (void)_PyXI_ApplyErrorCode(error->code, error->interp);
1073         if (error->uncaught.type.name != NULL || error->uncaught.msg != NULL) {
1074             // __context__ will be set to a proxy of the propagated exception.
1075             PyObject *exc = PyErr_GetRaisedException();
1076             _PyXI_excinfo_Apply(&error->uncaught, PyExc_InterpreterError);
1077             PyObject *exc2 = PyErr_GetRaisedException();
1078             PyException_SetContext(exc, exc2);
1079             PyErr_SetRaisedException(exc);
1080         }
1081     }
1082     assert(PyErr_Occurred());
1083     return NULL;
1084 }
1085 
1086 /* shared namespaces */
1087 
1088 /* Shared namespaces are expected to have relatively short lifetimes.
1089    This means dealloc of a shared namespace will normally happen "soon".
1090    Namespace items hold cross-interpreter data, which must get released.
1091    If the namespace/items are cleared in a different interpreter than
1092    where the items' cross-interpreter data was set then that will cause
1093    pending calls to be used to release the cross-interpreter data.
1094    The tricky bit is that the pending calls can happen sufficiently
1095    later that the namespace/items might already be deallocated.  This is
1096    a problem if the cross-interpreter data is allocated as part of a
1097    namespace item.  If that's the case then we must ensure the shared
1098    namespace is only cleared/freed *after* that data has been released. */
1099 
1100 typedef struct _sharednsitem {
1101     const char *name;
1102     _PyCrossInterpreterData *data;
1103     // We could have a "PyCrossInterpreterData _data" field, so it would
1104     // be allocated as part of the item and avoid an extra allocation.
1105     // However, doing so adds a bunch of complexity because we must
1106     // ensure the item isn't freed before a pending call might happen
1107     // in a different interpreter to release the XI data.
1108 } _PyXI_namespace_item;
1109 
1110 static int
_sharednsitem_is_initialized(_PyXI_namespace_item * item)1111 _sharednsitem_is_initialized(_PyXI_namespace_item *item)
1112 {
1113     if (item->name != NULL) {
1114         return 1;
1115     }
1116     return 0;
1117 }
1118 
1119 static int
_sharednsitem_init(_PyXI_namespace_item * item,PyObject * key)1120 _sharednsitem_init(_PyXI_namespace_item *item, PyObject *key)
1121 {
1122     item->name = _copy_string_obj_raw(key, NULL);
1123     if (item->name == NULL) {
1124         assert(!_sharednsitem_is_initialized(item));
1125         return -1;
1126     }
1127     item->data = NULL;
1128     assert(_sharednsitem_is_initialized(item));
1129     return 0;
1130 }
1131 
1132 static int
_sharednsitem_has_value(_PyXI_namespace_item * item,int64_t * p_interpid)1133 _sharednsitem_has_value(_PyXI_namespace_item *item, int64_t *p_interpid)
1134 {
1135     if (item->data == NULL) {
1136         return 0;
1137     }
1138     if (p_interpid != NULL) {
1139         *p_interpid = _PyCrossInterpreterData_INTERPID(item->data);
1140     }
1141     return 1;
1142 }
1143 
1144 static int
_sharednsitem_set_value(_PyXI_namespace_item * item,PyObject * value)1145 _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value)
1146 {
1147     assert(_sharednsitem_is_initialized(item));
1148     assert(item->data == NULL);
1149     item->data = PyMem_RawMalloc(sizeof(_PyCrossInterpreterData));
1150     if (item->data == NULL) {
1151         PyErr_NoMemory();
1152         return -1;
1153     }
1154     if (_PyObject_GetCrossInterpreterData(value, item->data) != 0) {
1155         PyMem_RawFree(item->data);
1156         item->data = NULL;
1157         // The caller may want to propagate PyExc_NotShareableError
1158         // if currently switched between interpreters.
1159         return -1;
1160     }
1161     return 0;
1162 }
1163 
1164 static void
_sharednsitem_clear_value(_PyXI_namespace_item * item)1165 _sharednsitem_clear_value(_PyXI_namespace_item *item)
1166 {
1167     _PyCrossInterpreterData *data = item->data;
1168     if (data != NULL) {
1169         item->data = NULL;
1170         int rawfree = 1;
1171         (void)_release_xid_data(data, rawfree);
1172     }
1173 }
1174 
1175 static void
_sharednsitem_clear(_PyXI_namespace_item * item)1176 _sharednsitem_clear(_PyXI_namespace_item *item)
1177 {
1178     if (item->name != NULL) {
1179         PyMem_RawFree((void *)item->name);
1180         item->name = NULL;
1181     }
1182     _sharednsitem_clear_value(item);
1183 }
1184 
1185 static int
_sharednsitem_copy_from_ns(struct _sharednsitem * item,PyObject * ns)1186 _sharednsitem_copy_from_ns(struct _sharednsitem *item, PyObject *ns)
1187 {
1188     assert(item->name != NULL);
1189     assert(item->data == NULL);
1190     PyObject *value = PyDict_GetItemString(ns, item->name);  // borrowed
1191     if (value == NULL) {
1192         if (PyErr_Occurred()) {
1193             return -1;
1194         }
1195         // When applied, this item will be set to the default (or fail).
1196         return 0;
1197     }
1198     if (_sharednsitem_set_value(item, value) < 0) {
1199         return -1;
1200     }
1201     return 0;
1202 }
1203 
1204 static int
_sharednsitem_apply(_PyXI_namespace_item * item,PyObject * ns,PyObject * dflt)1205 _sharednsitem_apply(_PyXI_namespace_item *item, PyObject *ns, PyObject *dflt)
1206 {
1207     PyObject *name = PyUnicode_FromString(item->name);
1208     if (name == NULL) {
1209         return -1;
1210     }
1211     PyObject *value;
1212     if (item->data != NULL) {
1213         value = _PyCrossInterpreterData_NewObject(item->data);
1214         if (value == NULL) {
1215             Py_DECREF(name);
1216             return -1;
1217         }
1218     }
1219     else {
1220         value = Py_NewRef(dflt);
1221     }
1222     int res = PyDict_SetItem(ns, name, value);
1223     Py_DECREF(name);
1224     Py_DECREF(value);
1225     return res;
1226 }
1227 
1228 struct _sharedns {
1229     Py_ssize_t len;
1230     _PyXI_namespace_item *items;
1231 };
1232 
1233 static _PyXI_namespace *
_sharedns_new(void)1234 _sharedns_new(void)
1235 {
1236     _PyXI_namespace *ns = PyMem_RawCalloc(sizeof(_PyXI_namespace), 1);
1237     if (ns == NULL) {
1238         PyErr_NoMemory();
1239         return NULL;
1240     }
1241     *ns = (_PyXI_namespace){ 0 };
1242     return ns;
1243 }
1244 
1245 static int
_sharedns_is_initialized(_PyXI_namespace * ns)1246 _sharedns_is_initialized(_PyXI_namespace *ns)
1247 {
1248     if (ns->len == 0) {
1249         assert(ns->items == NULL);
1250         return 0;
1251     }
1252 
1253     assert(ns->len > 0);
1254     assert(ns->items != NULL);
1255     assert(_sharednsitem_is_initialized(&ns->items[0]));
1256     assert(ns->len == 1
1257            || _sharednsitem_is_initialized(&ns->items[ns->len - 1]));
1258     return 1;
1259 }
1260 
1261 #define HAS_COMPLETE_DATA 1
1262 #define HAS_PARTIAL_DATA 2
1263 
1264 static int
_sharedns_has_xidata(_PyXI_namespace * ns,int64_t * p_interpid)1265 _sharedns_has_xidata(_PyXI_namespace *ns, int64_t *p_interpid)
1266 {
1267     // We expect _PyXI_namespace to always be initialized.
1268     assert(_sharedns_is_initialized(ns));
1269     int res = 0;
1270     _PyXI_namespace_item *item0 = &ns->items[0];
1271     if (!_sharednsitem_is_initialized(item0)) {
1272         return 0;
1273     }
1274     int64_t interpid0 = -1;
1275     if (!_sharednsitem_has_value(item0, &interpid0)) {
1276         return 0;
1277     }
1278     if (ns->len > 1) {
1279         // At this point we know it is has at least partial data.
1280         _PyXI_namespace_item *itemN = &ns->items[ns->len-1];
1281         if (!_sharednsitem_is_initialized(itemN)) {
1282             res = HAS_PARTIAL_DATA;
1283             goto finally;
1284         }
1285         int64_t interpidN = -1;
1286         if (!_sharednsitem_has_value(itemN, &interpidN)) {
1287             res = HAS_PARTIAL_DATA;
1288             goto finally;
1289         }
1290         assert(interpidN == interpid0);
1291     }
1292     res = HAS_COMPLETE_DATA;
1293     *p_interpid = interpid0;
1294 
1295 finally:
1296     return res;
1297 }
1298 
1299 static void
_sharedns_clear(_PyXI_namespace * ns)1300 _sharedns_clear(_PyXI_namespace *ns)
1301 {
1302     if (!_sharedns_is_initialized(ns)) {
1303         return;
1304     }
1305 
1306     // If the cross-interpreter data were allocated as part of
1307     // _PyXI_namespace_item (instead of dynamically), this is where
1308     // we would need verify that we are clearing the items in the
1309     // correct interpreter, to avoid a race with releasing the XI data
1310     // via a pending call.  See _sharedns_has_xidata().
1311     for (Py_ssize_t i=0; i < ns->len; i++) {
1312         _sharednsitem_clear(&ns->items[i]);
1313     }
1314     PyMem_RawFree(ns->items);
1315     ns->items = NULL;
1316     ns->len = 0;
1317 }
1318 
1319 static void
_sharedns_free(_PyXI_namespace * ns)1320 _sharedns_free(_PyXI_namespace *ns)
1321 {
1322     _sharedns_clear(ns);
1323     PyMem_RawFree(ns);
1324 }
1325 
1326 static int
_sharedns_init(_PyXI_namespace * ns,PyObject * names)1327 _sharedns_init(_PyXI_namespace *ns, PyObject *names)
1328 {
1329     assert(!_sharedns_is_initialized(ns));
1330     assert(names != NULL);
1331     Py_ssize_t len = PyDict_CheckExact(names)
1332         ? PyDict_Size(names)
1333         : PySequence_Size(names);
1334     if (len < 0) {
1335         return -1;
1336     }
1337     if (len == 0) {
1338         PyErr_SetString(PyExc_ValueError, "empty namespaces not allowed");
1339         return -1;
1340     }
1341     assert(len > 0);
1342 
1343     // Allocate the items.
1344     _PyXI_namespace_item *items =
1345             PyMem_RawCalloc(sizeof(struct _sharednsitem), len);
1346     if (items == NULL) {
1347         PyErr_NoMemory();
1348         return -1;
1349     }
1350 
1351     // Fill in the names.
1352     Py_ssize_t i = -1;
1353     if (PyDict_CheckExact(names)) {
1354         Py_ssize_t pos = 0;
1355         for (i=0; i < len; i++) {
1356             PyObject *key;
1357             if (!PyDict_Next(names, &pos, &key, NULL)) {
1358                 // This should not be possible.
1359                 assert(0);
1360                 goto error;
1361             }
1362             if (_sharednsitem_init(&items[i], key) < 0) {
1363                 goto error;
1364             }
1365         }
1366     }
1367     else if (PySequence_Check(names)) {
1368         for (i=0; i < len; i++) {
1369             PyObject *key = PySequence_GetItem(names, i);
1370             if (key == NULL) {
1371                 goto error;
1372             }
1373             int res = _sharednsitem_init(&items[i], key);
1374             Py_DECREF(key);
1375             if (res < 0) {
1376                 goto error;
1377             }
1378         }
1379     }
1380     else {
1381         PyErr_SetString(PyExc_NotImplementedError,
1382                         "non-sequence namespace not supported");
1383         goto error;
1384     }
1385 
1386     ns->items = items;
1387     ns->len = len;
1388     assert(_sharedns_is_initialized(ns));
1389     return 0;
1390 
1391 error:
1392     for (Py_ssize_t j=0; j < i; j++) {
1393         _sharednsitem_clear(&items[j]);
1394     }
1395     PyMem_RawFree(items);
1396     assert(!_sharedns_is_initialized(ns));
1397     return -1;
1398 }
1399 
1400 void
_PyXI_FreeNamespace(_PyXI_namespace * ns)1401 _PyXI_FreeNamespace(_PyXI_namespace *ns)
1402 {
1403     if (!_sharedns_is_initialized(ns)) {
1404         return;
1405     }
1406 
1407     int64_t interpid = -1;
1408     if (!_sharedns_has_xidata(ns, &interpid)) {
1409         _sharedns_free(ns);
1410         return;
1411     }
1412 
1413     if (interpid == PyInterpreterState_GetID(PyInterpreterState_Get())) {
1414         _sharedns_free(ns);
1415     }
1416     else {
1417         // If we weren't always dynamically allocating the cross-interpreter
1418         // data in each item then we would need to using a pending call
1419         // to call _sharedns_free(), to avoid the race between freeing
1420         // the shared namespace and releasing the XI data.
1421         _sharedns_free(ns);
1422     }
1423 }
1424 
1425 _PyXI_namespace *
_PyXI_NamespaceFromNames(PyObject * names)1426 _PyXI_NamespaceFromNames(PyObject *names)
1427 {
1428     if (names == NULL || names == Py_None) {
1429         return NULL;
1430     }
1431 
1432     _PyXI_namespace *ns = _sharedns_new();
1433     if (ns == NULL) {
1434         return NULL;
1435     }
1436 
1437     if (_sharedns_init(ns, names) < 0) {
1438         PyMem_RawFree(ns);
1439         if (PySequence_Size(names) == 0) {
1440             PyErr_Clear();
1441         }
1442         return NULL;
1443     }
1444 
1445     return ns;
1446 }
1447 
1448 #ifndef NDEBUG
1449 static int _session_is_active(_PyXI_session *);
1450 #endif
1451 static void _propagate_not_shareable_error(_PyXI_session *);
1452 
1453 int
_PyXI_FillNamespaceFromDict(_PyXI_namespace * ns,PyObject * nsobj,_PyXI_session * session)1454 _PyXI_FillNamespaceFromDict(_PyXI_namespace *ns, PyObject *nsobj,
1455                             _PyXI_session *session)
1456 {
1457     // session must be entered already, if provided.
1458     assert(session == NULL || _session_is_active(session));
1459     assert(_sharedns_is_initialized(ns));
1460     for (Py_ssize_t i=0; i < ns->len; i++) {
1461         _PyXI_namespace_item *item = &ns->items[i];
1462         if (_sharednsitem_copy_from_ns(item, nsobj) < 0) {
1463             _propagate_not_shareable_error(session);
1464             // Clear out the ones we set so far.
1465             for (Py_ssize_t j=0; j < i; j++) {
1466                 _sharednsitem_clear_value(&ns->items[j]);
1467             }
1468             return -1;
1469         }
1470     }
1471     return 0;
1472 }
1473 
1474 // All items are expected to be shareable.
1475 static _PyXI_namespace *
_PyXI_NamespaceFromDict(PyObject * nsobj,_PyXI_session * session)1476 _PyXI_NamespaceFromDict(PyObject *nsobj, _PyXI_session *session)
1477 {
1478     // session must be entered already, if provided.
1479     assert(session == NULL || _session_is_active(session));
1480     if (nsobj == NULL || nsobj == Py_None) {
1481         return NULL;
1482     }
1483     if (!PyDict_CheckExact(nsobj)) {
1484         PyErr_SetString(PyExc_TypeError, "expected a dict");
1485         return NULL;
1486     }
1487 
1488     _PyXI_namespace *ns = _sharedns_new();
1489     if (ns == NULL) {
1490         return NULL;
1491     }
1492 
1493     if (_sharedns_init(ns, nsobj) < 0) {
1494         if (PyDict_Size(nsobj) == 0) {
1495             PyMem_RawFree(ns);
1496             PyErr_Clear();
1497             return NULL;
1498         }
1499         goto error;
1500     }
1501 
1502     if (_PyXI_FillNamespaceFromDict(ns, nsobj, session) < 0) {
1503         goto error;
1504     }
1505 
1506     return ns;
1507 
1508 error:
1509     assert(PyErr_Occurred()
1510            || (session != NULL && session->error_override != NULL));
1511     _sharedns_free(ns);
1512     return NULL;
1513 }
1514 
1515 int
_PyXI_ApplyNamespace(_PyXI_namespace * ns,PyObject * nsobj,PyObject * dflt)1516 _PyXI_ApplyNamespace(_PyXI_namespace *ns, PyObject *nsobj, PyObject *dflt)
1517 {
1518     for (Py_ssize_t i=0; i < ns->len; i++) {
1519         if (_sharednsitem_apply(&ns->items[i], nsobj, dflt) != 0) {
1520             return -1;
1521         }
1522     }
1523     return 0;
1524 }
1525 
1526 
1527 /**********************/
1528 /* high-level helpers */
1529 /**********************/
1530 
1531 /* enter/exit a cross-interpreter session */
1532 
1533 static void
_enter_session(_PyXI_session * session,PyInterpreterState * interp)1534 _enter_session(_PyXI_session *session, PyInterpreterState *interp)
1535 {
1536     // Set here and cleared in _exit_session().
1537     assert(!session->own_init_tstate);
1538     assert(session->init_tstate == NULL);
1539     assert(session->prev_tstate == NULL);
1540     // Set elsewhere and cleared in _exit_session().
1541     assert(!session->running);
1542     assert(session->main_ns == NULL);
1543     // Set elsewhere and cleared in _capture_current_exception().
1544     assert(session->error_override == NULL);
1545     // Set elsewhere and cleared in _PyXI_ApplyCapturedException().
1546     assert(session->error == NULL);
1547 
1548     // Switch to interpreter.
1549     PyThreadState *tstate = PyThreadState_Get();
1550     PyThreadState *prev = tstate;
1551     if (interp != tstate->interp) {
1552         tstate = _PyThreadState_NewBound(interp, _PyThreadState_WHENCE_EXEC);
1553         // XXX Possible GILState issues?
1554         session->prev_tstate = PyThreadState_Swap(tstate);
1555         assert(session->prev_tstate == prev);
1556         session->own_init_tstate = 1;
1557     }
1558     session->init_tstate = tstate;
1559     session->prev_tstate = prev;
1560 }
1561 
1562 static void
_exit_session(_PyXI_session * session)1563 _exit_session(_PyXI_session *session)
1564 {
1565     PyThreadState *tstate = session->init_tstate;
1566     assert(tstate != NULL);
1567     assert(PyThreadState_Get() == tstate);
1568 
1569     // Release any of the entered interpreters resources.
1570     if (session->main_ns != NULL) {
1571         Py_CLEAR(session->main_ns);
1572     }
1573 
1574     // Ensure this thread no longer owns __main__.
1575     if (session->running) {
1576         _PyInterpreterState_SetNotRunningMain(tstate->interp);
1577         assert(!PyErr_Occurred());
1578         session->running = 0;
1579     }
1580 
1581     // Switch back.
1582     assert(session->prev_tstate != NULL);
1583     if (session->prev_tstate != session->init_tstate) {
1584         assert(session->own_init_tstate);
1585         session->own_init_tstate = 0;
1586         PyThreadState_Clear(tstate);
1587         PyThreadState_Swap(session->prev_tstate);
1588         PyThreadState_Delete(tstate);
1589     }
1590     else {
1591         assert(!session->own_init_tstate);
1592     }
1593     session->prev_tstate = NULL;
1594     session->init_tstate = NULL;
1595 }
1596 
1597 #ifndef NDEBUG
1598 static int
_session_is_active(_PyXI_session * session)1599 _session_is_active(_PyXI_session *session)
1600 {
1601     return (session->init_tstate != NULL);
1602 }
1603 #endif
1604 
1605 static void
_propagate_not_shareable_error(_PyXI_session * session)1606 _propagate_not_shareable_error(_PyXI_session *session)
1607 {
1608     if (session == NULL) {
1609         return;
1610     }
1611     PyInterpreterState *interp = PyInterpreterState_Get();
1612     if (PyErr_ExceptionMatches(_get_not_shareable_error_type(interp))) {
1613         // We want to propagate the exception directly.
1614         session->_error_override = _PyXI_ERR_NOT_SHAREABLE;
1615         session->error_override = &session->_error_override;
1616     }
1617 }
1618 
1619 static void
_capture_current_exception(_PyXI_session * session)1620 _capture_current_exception(_PyXI_session *session)
1621 {
1622     assert(session->error == NULL);
1623     if (!PyErr_Occurred()) {
1624         assert(session->error_override == NULL);
1625         return;
1626     }
1627 
1628     // Handle the exception override.
1629     _PyXI_errcode *override = session->error_override;
1630     session->error_override = NULL;
1631     _PyXI_errcode errcode = override != NULL
1632         ? *override
1633         : _PyXI_ERR_UNCAUGHT_EXCEPTION;
1634 
1635     // Pop the exception object.
1636     PyObject *excval = NULL;
1637     if (errcode == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
1638         // We want to actually capture the current exception.
1639         excval = PyErr_GetRaisedException();
1640     }
1641     else if (errcode == _PyXI_ERR_ALREADY_RUNNING) {
1642         // We don't need the exception info.
1643         PyErr_Clear();
1644     }
1645     else {
1646         // We could do a variety of things here, depending on errcode.
1647         // However, for now we simply capture the exception and save
1648         // the errcode.
1649         excval = PyErr_GetRaisedException();
1650     }
1651 
1652     // Capture the exception.
1653     _PyXI_error *err = &session->_error;
1654     *err = (_PyXI_error){
1655         .interp = session->init_tstate->interp,
1656     };
1657     const char *failure;
1658     if (excval == NULL) {
1659         failure = _PyXI_InitError(err, NULL, errcode);
1660     }
1661     else {
1662         failure = _PyXI_InitError(err, excval, _PyXI_ERR_UNCAUGHT_EXCEPTION);
1663         Py_DECREF(excval);
1664         if (failure == NULL && override != NULL) {
1665             err->code = errcode;
1666         }
1667     }
1668 
1669     // Handle capture failure.
1670     if (failure != NULL) {
1671         // XXX Make this error message more generic.
1672         fprintf(stderr,
1673                 "RunFailedError: script raised an uncaught exception (%s)",
1674                 failure);
1675         err = NULL;
1676     }
1677 
1678     // Finished!
1679     assert(!PyErr_Occurred());
1680     session->error  = err;
1681 }
1682 
1683 PyObject *
_PyXI_ApplyCapturedException(_PyXI_session * session)1684 _PyXI_ApplyCapturedException(_PyXI_session *session)
1685 {
1686     assert(!PyErr_Occurred());
1687     assert(session->error != NULL);
1688     PyObject *res = _PyXI_ApplyError(session->error);
1689     assert((res == NULL) != (PyErr_Occurred() == NULL));
1690     session->error = NULL;
1691     return res;
1692 }
1693 
1694 int
_PyXI_HasCapturedException(_PyXI_session * session)1695 _PyXI_HasCapturedException(_PyXI_session *session)
1696 {
1697     return session->error != NULL;
1698 }
1699 
1700 int
_PyXI_Enter(_PyXI_session * session,PyInterpreterState * interp,PyObject * nsupdates)1701 _PyXI_Enter(_PyXI_session *session,
1702             PyInterpreterState *interp, PyObject *nsupdates)
1703 {
1704     // Convert the attrs for cross-interpreter use.
1705     _PyXI_namespace *sharedns = NULL;
1706     if (nsupdates != NULL) {
1707         sharedns = _PyXI_NamespaceFromDict(nsupdates, NULL);
1708         if (sharedns == NULL && PyErr_Occurred()) {
1709             assert(session->error == NULL);
1710             return -1;
1711         }
1712     }
1713 
1714     // Switch to the requested interpreter (if necessary).
1715     _enter_session(session, interp);
1716     _PyXI_errcode errcode = _PyXI_ERR_UNCAUGHT_EXCEPTION;
1717 
1718     // Ensure this thread owns __main__.
1719     if (_PyInterpreterState_SetRunningMain(interp) < 0) {
1720         // In the case where we didn't switch interpreters, it would
1721         // be more efficient to leave the exception in place and return
1722         // immediately.  However, life is simpler if we don't.
1723         errcode = _PyXI_ERR_ALREADY_RUNNING;
1724         goto error;
1725     }
1726     session->running = 1;
1727 
1728     // Cache __main__.__dict__.
1729     PyObject *main_mod = PyUnstable_InterpreterState_GetMainModule(interp);
1730     if (main_mod == NULL) {
1731         errcode = _PyXI_ERR_MAIN_NS_FAILURE;
1732         goto error;
1733     }
1734     PyObject *ns = PyModule_GetDict(main_mod);  // borrowed
1735     Py_DECREF(main_mod);
1736     if (ns == NULL) {
1737         errcode = _PyXI_ERR_MAIN_NS_FAILURE;
1738         goto error;
1739     }
1740     session->main_ns = Py_NewRef(ns);
1741 
1742     // Apply the cross-interpreter data.
1743     if (sharedns != NULL) {
1744         if (_PyXI_ApplyNamespace(sharedns, ns, NULL) < 0) {
1745             errcode = _PyXI_ERR_APPLY_NS_FAILURE;
1746             goto error;
1747         }
1748         _PyXI_FreeNamespace(sharedns);
1749     }
1750 
1751     errcode = _PyXI_ERR_NO_ERROR;
1752     assert(!PyErr_Occurred());
1753     return 0;
1754 
1755 error:
1756     assert(PyErr_Occurred());
1757     // We want to propagate all exceptions here directly (best effort).
1758     assert(errcode != _PyXI_ERR_UNCAUGHT_EXCEPTION);
1759     session->error_override = &errcode;
1760     _capture_current_exception(session);
1761     _exit_session(session);
1762     if (sharedns != NULL) {
1763         _PyXI_FreeNamespace(sharedns);
1764     }
1765     return -1;
1766 }
1767 
1768 void
_PyXI_Exit(_PyXI_session * session)1769 _PyXI_Exit(_PyXI_session *session)
1770 {
1771     _capture_current_exception(session);
1772     _exit_session(session);
1773 }
1774 
1775 
1776 /*********************/
1777 /* runtime lifecycle */
1778 /*********************/
1779 
1780 PyStatus
_PyXI_Init(PyInterpreterState * interp)1781 _PyXI_Init(PyInterpreterState *interp)
1782 {
1783     // Initialize the XID lookup state (e.g. registry).
1784     xid_lookup_init(interp);
1785 
1786     // Initialize exceptions (heap types).
1787     if (_init_not_shareable_error_type(interp) < 0) {
1788         return _PyStatus_ERR("failed to initialize NotShareableError");
1789     }
1790 
1791     return _PyStatus_OK();
1792 }
1793 
1794 // _PyXI_Fini() must be called before the interpreter is cleared,
1795 // since we must clear some heap objects.
1796 
1797 void
_PyXI_Fini(PyInterpreterState * interp)1798 _PyXI_Fini(PyInterpreterState *interp)
1799 {
1800     // Finalize exceptions (heap types).
1801     _fini_not_shareable_error_type(interp);
1802 
1803     // Finalize the XID lookup state (e.g. registry).
1804     xid_lookup_fini(interp);
1805 }
1806 
1807 PyStatus
_PyXI_InitTypes(PyInterpreterState * interp)1808 _PyXI_InitTypes(PyInterpreterState *interp)
1809 {
1810     if (init_exceptions(interp) < 0) {
1811         PyErr_PrintEx(0);
1812         return _PyStatus_ERR("failed to initialize an exception type");
1813     }
1814     return _PyStatus_OK();
1815 }
1816 
1817 void
_PyXI_FiniTypes(PyInterpreterState * interp)1818 _PyXI_FiniTypes(PyInterpreterState *interp)
1819 {
1820     fini_exceptions(interp);
1821 }
1822 
1823 
1824 /*************/
1825 /* other API */
1826 /*************/
1827 
1828 PyInterpreterState *
_PyXI_NewInterpreter(PyInterpreterConfig * config,long * maybe_whence,PyThreadState ** p_tstate,PyThreadState ** p_save_tstate)1829 _PyXI_NewInterpreter(PyInterpreterConfig *config, long *maybe_whence,
1830                      PyThreadState **p_tstate, PyThreadState **p_save_tstate)
1831 {
1832     PyThreadState *save_tstate = PyThreadState_Swap(NULL);
1833     assert(save_tstate != NULL);
1834 
1835     PyThreadState *tstate;
1836     PyStatus status = Py_NewInterpreterFromConfig(&tstate, config);
1837     if (PyStatus_Exception(status)) {
1838         // Since no new thread state was created, there is no exception
1839         // to propagate; raise a fresh one after swapping back in the
1840         // old thread state.
1841         PyThreadState_Swap(save_tstate);
1842         _PyErr_SetFromPyStatus(status);
1843         PyObject *exc = PyErr_GetRaisedException();
1844         PyErr_SetString(PyExc_InterpreterError,
1845                         "sub-interpreter creation failed");
1846         _PyErr_ChainExceptions1(exc);
1847         return NULL;
1848     }
1849     assert(tstate != NULL);
1850     PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
1851 
1852     long whence = _PyInterpreterState_WHENCE_XI;
1853     if (maybe_whence != NULL) {
1854         whence = *maybe_whence;
1855     }
1856     _PyInterpreterState_SetWhence(interp, whence);
1857 
1858     if (p_tstate != NULL) {
1859         // We leave the new thread state as the current one.
1860         *p_tstate = tstate;
1861     }
1862     else {
1863         // Throw away the initial tstate.
1864         PyThreadState_Clear(tstate);
1865         PyThreadState_Swap(save_tstate);
1866         PyThreadState_Delete(tstate);
1867         save_tstate = NULL;
1868     }
1869     if (p_save_tstate != NULL) {
1870         *p_save_tstate = save_tstate;
1871     }
1872     return interp;
1873 }
1874 
1875 void
_PyXI_EndInterpreter(PyInterpreterState * interp,PyThreadState * tstate,PyThreadState ** p_save_tstate)1876 _PyXI_EndInterpreter(PyInterpreterState *interp,
1877                      PyThreadState *tstate, PyThreadState **p_save_tstate)
1878 {
1879 #ifndef NDEBUG
1880     long whence = _PyInterpreterState_GetWhence(interp);
1881 #endif
1882     assert(whence != _PyInterpreterState_WHENCE_RUNTIME);
1883 
1884     if (!_PyInterpreterState_IsReady(interp)) {
1885         assert(whence == _PyInterpreterState_WHENCE_UNKNOWN);
1886         // PyInterpreterState_Clear() requires the GIL,
1887         // which a not-ready does not have, so we don't clear it.
1888         // That means there may be leaks here until clearing the
1889         // interpreter is fixed.
1890         PyInterpreterState_Delete(interp);
1891         return;
1892     }
1893     assert(whence != _PyInterpreterState_WHENCE_UNKNOWN);
1894 
1895     PyThreadState *save_tstate = NULL;
1896     PyThreadState *cur_tstate = PyThreadState_GET();
1897     if (tstate == NULL) {
1898         if (PyThreadState_GetInterpreter(cur_tstate) == interp) {
1899             tstate = cur_tstate;
1900         }
1901         else {
1902             tstate = _PyThreadState_NewBound(interp, _PyThreadState_WHENCE_FINI);
1903             assert(tstate != NULL);
1904             save_tstate = PyThreadState_Swap(tstate);
1905         }
1906     }
1907     else {
1908         assert(PyThreadState_GetInterpreter(tstate) == interp);
1909         if (tstate != cur_tstate) {
1910             assert(PyThreadState_GetInterpreter(cur_tstate) != interp);
1911             save_tstate = PyThreadState_Swap(tstate);
1912         }
1913     }
1914 
1915     Py_EndInterpreter(tstate);
1916 
1917     if (p_save_tstate != NULL) {
1918         save_tstate = *p_save_tstate;
1919     }
1920     PyThreadState_Swap(save_tstate);
1921 }
1922