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