Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/crossinterp.c
Line
Count
Source
1
2
/* API for managing interactions between isolated interpreters */
3
4
#include "Python.h"
5
#include "marshal.h"              // PyMarshal_WriteObjectToString()
6
#include "osdefs.h"               // MAXPATHLEN
7
#include "pycore_ceval.h"         // _Py_simple_func
8
#include "pycore_crossinterp.h"   // _PyXIData_t
9
#include "pycore_function.h"      // _PyFunction_VerifyStateless()
10
#include "pycore_global_strings.h"  // _Py_ID()
11
#include "pycore_import.h"        // _PyImport_SetModule()
12
#include "pycore_initconfig.h"    // _PyStatus_OK()
13
#include "pycore_namespace.h"     // _PyNamespace_New()
14
#include "pycore_pythonrun.h"     // _Py_SourceAsString()
15
#include "pycore_runtime.h"       // _PyRuntime
16
#include "pycore_setobject.h"     // _PySet_NextEntry()
17
#include "pycore_typeobject.h"    // _PyStaticType_InitBuiltin()
18
19
20
static Py_ssize_t
21
_Py_GetMainfile(char *buffer, size_t maxlen)
22
0
{
23
    // We don't expect subinterpreters to have the __main__ module's
24
    // __name__ set, but proceed just in case.
25
0
    PyThreadState *tstate = _PyThreadState_GET();
26
0
    PyObject *module = _Py_GetMainModule(tstate);
27
0
    if (_Py_CheckMainModule(module) < 0) {
28
0
        Py_XDECREF(module);
29
0
        return -1;
30
0
    }
31
0
    Py_ssize_t size = _PyModule_GetFilenameUTF8(module, buffer, maxlen);
32
0
    Py_DECREF(module);
33
0
    return size;
34
0
}
35
36
37
static PyObject *
38
runpy_run_path(const char *filename, const char *modname)
39
0
{
40
0
    PyObject *run_path = PyImport_ImportModuleAttrString("runpy", "run_path");
41
0
    if (run_path == NULL) {
42
0
        return NULL;
43
0
    }
44
0
    PyObject *args = Py_BuildValue("(sOs)", filename, Py_None, modname);
45
0
    if (args == NULL) {
46
0
        Py_DECREF(run_path);
47
0
        return NULL;
48
0
    }
49
0
    PyObject *ns = PyObject_Call(run_path, args, NULL);
50
0
    Py_DECREF(run_path);
51
0
    Py_DECREF(args);
52
0
    return ns;
53
0
}
54
55
56
static void
57
set_exc_with_cause(PyObject *exctype, const char *msg)
58
0
{
59
0
    PyObject *cause = PyErr_GetRaisedException();
60
0
    PyErr_SetString(exctype, msg);
61
0
    PyObject *exc = PyErr_GetRaisedException();
62
0
    PyException_SetCause(exc, cause);
63
0
    PyErr_SetRaisedException(exc);
64
0
}
65
66
67
/****************************/
68
/* module duplication utils */
69
/****************************/
70
71
struct sync_module_result {
72
    PyObject *module;
73
    PyObject *loaded;
74
    PyObject *failed;
75
};
76
77
struct sync_module {
78
    const char *filename;
79
    char _filename[MAXPATHLEN+1];
80
    struct sync_module_result cached;
81
};
82
83
static void
84
sync_module_clear(struct sync_module *data)
85
0
{
86
0
    data->filename = NULL;
87
0
    Py_CLEAR(data->cached.module);
88
0
    Py_CLEAR(data->cached.loaded);
89
0
    Py_CLEAR(data->cached.failed);
90
0
}
91
92
static void
93
sync_module_capture_exc(PyThreadState *tstate, struct sync_module *data)
94
0
{
95
0
    assert(_PyErr_Occurred(tstate));
96
0
    PyObject *context = data->cached.failed;
97
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
98
0
    _PyErr_SetRaisedException(tstate, Py_NewRef(exc));
99
0
    if (context != NULL) {
100
0
        PyException_SetContext(exc, context);
101
0
    }
102
0
    data->cached.failed = exc;
103
0
}
104
105
106
static int
107
ensure_isolated_main(PyThreadState *tstate, struct sync_module *main)
108
0
{
109
    // Load the module from the original file (or from a cache).
110
111
    // First try the local cache.
112
0
    if (main->cached.failed != NULL) {
113
        // We'll deal with this in apply_isolated_main().
114
0
        assert(main->cached.module == NULL);
115
0
        assert(main->cached.loaded == NULL);
116
0
        return 0;
117
0
    }
118
0
    else if (main->cached.loaded != NULL) {
119
0
        assert(main->cached.module != NULL);
120
0
        return 0;
121
0
    }
122
0
    assert(main->cached.module == NULL);
123
124
0
    if (main->filename == NULL) {
125
0
        _PyErr_SetString(tstate, PyExc_NotImplementedError, "");
126
0
        return -1;
127
0
    }
128
129
    // It wasn't in the local cache so we'll need to populate it.
130
0
    PyObject *mod = _Py_GetMainModule(tstate);
131
0
    if (_Py_CheckMainModule(mod) < 0) {
132
        // This is probably unrecoverable, so don't bother caching the error.
133
0
        assert(_PyErr_Occurred(tstate));
134
0
        Py_XDECREF(mod);
135
0
        return -1;
136
0
    }
137
0
    PyObject *loaded = NULL;
138
139
    // Try the per-interpreter cache for the loaded module.
140
    // XXX Store it in sys.modules?
141
0
    PyObject *interpns = PyInterpreterState_GetDict(tstate->interp);
142
0
    assert(interpns != NULL);
143
0
    PyObject *key = PyUnicode_FromString("CACHED_MODULE_NS___main__");
144
0
    if (key == NULL) {
145
        // It's probably unrecoverable, so don't bother caching the error.
146
0
        Py_DECREF(mod);
147
0
        return -1;
148
0
    }
149
0
    else if (PyDict_GetItemRef(interpns, key, &loaded) < 0) {
150
        // It's probably unrecoverable, so don't bother caching the error.
151
0
        Py_DECREF(mod);
152
0
        Py_DECREF(key);
153
0
        return -1;
154
0
    }
155
0
    else if (loaded == NULL) {
156
        // It wasn't already loaded from file.
157
0
        loaded = PyModule_NewObject(&_Py_ID(__main__));
158
0
        if (loaded == NULL) {
159
0
            goto error;
160
0
        }
161
0
        PyObject *ns = _PyModule_GetDict(loaded);
162
163
        // We don't want to trigger "if __name__ == '__main__':",
164
        // so we use a bogus module name.
165
0
        PyObject *loaded_ns =
166
0
                    runpy_run_path(main->filename, "<fake __main__>");
167
0
        if (loaded_ns == NULL) {
168
0
            goto error;
169
0
        }
170
0
        int res = PyDict_Update(ns, loaded_ns);
171
0
        Py_DECREF(loaded_ns);
172
0
        if (res < 0) {
173
0
            goto error;
174
0
        }
175
176
        // Set the per-interpreter cache entry.
177
0
        if (PyDict_SetItem(interpns, key, loaded) < 0) {
178
0
            goto error;
179
0
        }
180
0
    }
181
182
0
    Py_DECREF(key);
183
0
    main->cached = (struct sync_module_result){
184
0
       .module = mod,
185
0
       .loaded = loaded,
186
0
    };
187
0
    return 0;
188
189
0
error:
190
0
    sync_module_capture_exc(tstate, main);
191
0
    Py_XDECREF(loaded);
192
0
    Py_DECREF(mod);
193
0
    Py_XDECREF(key);
194
0
    return -1;
195
0
}
196
197
#ifndef NDEBUG
198
static int
199
main_mod_matches(PyObject *expected)
200
{
201
    PyObject *mod = PyImport_GetModule(&_Py_ID(__main__));
202
    Py_XDECREF(mod);
203
    return mod == expected;
204
}
205
#endif
206
207
static int
208
apply_isolated_main(PyThreadState *tstate, struct sync_module *main)
209
0
{
210
0
    assert((main->cached.loaded == NULL) == (main->cached.loaded == NULL));
211
0
    if (main->cached.failed != NULL) {
212
        // It must have failed previously.
213
0
        assert(main->cached.loaded == NULL);
214
0
        _PyErr_SetRaisedException(tstate, main->cached.failed);
215
0
        return -1;
216
0
    }
217
0
    assert(main->cached.loaded != NULL);
218
219
0
    assert(main_mod_matches(main->cached.module));
220
0
    if (_PyImport_SetModule(&_Py_ID(__main__), main->cached.loaded) < 0) {
221
0
        sync_module_capture_exc(tstate, main);
222
0
        return -1;
223
0
    }
224
0
    return 0;
225
0
}
226
227
static void
228
restore_main(PyThreadState *tstate, struct sync_module *main)
229
0
{
230
0
    assert(main->cached.failed == NULL);
231
0
    assert(main->cached.module != NULL);
232
0
    assert(main->cached.loaded != NULL);
233
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
234
0
    assert(main_mod_matches(main->cached.loaded));
235
0
    int res = _PyImport_SetModule(&_Py_ID(__main__), main->cached.module);
236
0
    assert(res == 0);
237
0
    if (res < 0) {
238
0
        PyErr_FormatUnraisable("Exception ignored while restoring __main__");
239
0
    }
240
0
    _PyErr_SetRaisedException(tstate, exc);
241
0
}
242
243
244
/**************/
245
/* exceptions */
246
/**************/
247
248
typedef struct xi_exceptions exceptions_t;
249
static int init_static_exctypes(exceptions_t *, PyInterpreterState *);
250
static void fini_static_exctypes(exceptions_t *, PyInterpreterState *);
251
static int init_heap_exctypes(exceptions_t *);
252
static void fini_heap_exctypes(exceptions_t *);
253
#include "crossinterp_exceptions.h"
254
255
256
/***************************/
257
/* cross-interpreter calls */
258
/***************************/
259
260
int
261
_Py_CallInInterpreter(PyInterpreterState *interp,
262
                      _Py_simple_func func, void *arg)
263
0
{
264
0
    if (interp == PyInterpreterState_Get()) {
265
0
        return func(arg);
266
0
    }
267
    // XXX Emit a warning if this fails?
268
0
    _PyEval_AddPendingCall(interp, (_Py_pending_call_func)func, arg, 0);
269
0
    return 0;
270
0
}
271
272
int
273
_Py_CallInInterpreterAndRawFree(PyInterpreterState *interp,
274
                                _Py_simple_func func, void *arg)
275
0
{
276
0
    if (interp == PyInterpreterState_Get()) {
277
0
        int res = func(arg);
278
0
        PyMem_RawFree(arg);
279
0
        return res;
280
0
    }
281
    // XXX Emit a warning if this fails?
282
0
    _PyEval_AddPendingCall(interp, func, arg, _Py_PENDING_RAWFREE);
283
0
    return 0;
284
0
}
285
286
287
/**************************/
288
/* cross-interpreter data */
289
/**************************/
290
291
/* registry of {type -> _PyXIData_getdata_t} */
292
293
/* For now we use a global registry of shareable classes.
294
   An alternative would be to add a tp_* slot for a class's
295
   _PyXIData_getdata_t.  It would be simpler and more efficient. */
296
297
static void xid_lookup_init(_PyXIData_lookup_t *);
298
static void xid_lookup_fini(_PyXIData_lookup_t *);
299
struct _dlcontext;
300
static _PyXIData_getdata_t lookup_getdata(struct _dlcontext *, PyObject *);
301
#include "crossinterp_data_lookup.h"
302
303
304
/* lifecycle */
305
306
_PyXIData_t *
307
_PyXIData_New(void)
308
0
{
309
0
    _PyXIData_t *xid = PyMem_RawCalloc(1, sizeof(_PyXIData_t));
310
0
    if (xid == NULL) {
311
0
        PyErr_NoMemory();
312
0
    }
313
0
    return xid;
314
0
}
315
316
void
317
_PyXIData_Free(_PyXIData_t *xid)
318
0
{
319
0
    PyInterpreterState *interp = PyInterpreterState_Get();
320
0
    _PyXIData_Clear(interp, xid);
321
0
    PyMem_RawFree(xid);
322
0
}
323
324
325
/* defining cross-interpreter data */
326
327
static inline void
328
_xidata_init(_PyXIData_t *xidata)
329
0
{
330
    // If the value is being reused
331
    // then _xidata_clear() should have been called already.
332
0
    assert(xidata->data == NULL);
333
0
    assert(xidata->obj == NULL);
334
0
    *xidata = (_PyXIData_t){0};
335
0
    _PyXIData_INTERPID(xidata) = -1;
336
0
}
337
338
static inline void
339
_xidata_clear(_PyXIData_t *xidata)
340
0
{
341
    // _PyXIData_t only has two members that need to be
342
    // cleaned up, if set: "xidata" must be freed and "obj" must be decref'ed.
343
    // In both cases the original (owning) interpreter must be used,
344
    // which is the caller's responsibility to ensure.
345
0
    if (xidata->data != NULL) {
346
0
        if (xidata->free != NULL) {
347
0
            xidata->free(xidata->data);
348
0
        }
349
0
        xidata->data = NULL;
350
0
    }
351
0
    Py_CLEAR(xidata->obj);
352
0
}
353
354
void
355
_PyXIData_Init(_PyXIData_t *xidata,
356
               PyInterpreterState *interp,
357
               void *shared, PyObject *obj,
358
               xid_newobjfunc new_object)
359
0
{
360
0
    assert(xidata != NULL);
361
0
    assert(new_object != NULL);
362
0
    _xidata_init(xidata);
363
0
    xidata->data = shared;
364
0
    if (obj != NULL) {
365
0
        assert(interp != NULL);
366
        // released in _PyXIData_Clear()
367
0
        xidata->obj = Py_NewRef(obj);
368
0
    }
369
    // Ideally every object would know its owning interpreter.
370
    // Until then, we have to rely on the caller to identify it
371
    // (but we don't need it in all cases).
372
0
    _PyXIData_INTERPID(xidata) = (interp != NULL)
373
0
        ? PyInterpreterState_GetID(interp)
374
0
        : -1;
375
0
    xidata->new_object = new_object;
376
0
}
377
378
int
379
_PyXIData_InitWithSize(_PyXIData_t *xidata,
380
                       PyInterpreterState *interp,
381
                       const size_t size, PyObject *obj,
382
                       xid_newobjfunc new_object)
383
0
{
384
0
    assert(size > 0);
385
    // For now we always free the shared data in the same interpreter
386
    // where it was allocated, so the interpreter is required.
387
0
    assert(interp != NULL);
388
0
    _PyXIData_Init(xidata, interp, NULL, obj, new_object);
389
0
    xidata->data = PyMem_RawCalloc(1, size);
390
0
    if (xidata->data == NULL) {
391
0
        return -1;
392
0
    }
393
0
    xidata->free = PyMem_RawFree;
394
0
    return 0;
395
0
}
396
397
void
398
_PyXIData_Clear(PyInterpreterState *interp, _PyXIData_t *xidata)
399
0
{
400
0
    assert(xidata != NULL);
401
    // This must be called in the owning interpreter.
402
0
    assert(interp == NULL
403
0
           || _PyXIData_INTERPID(xidata) == -1
404
0
           || _PyXIData_INTERPID(xidata) == PyInterpreterState_GetID(interp));
405
0
    _xidata_clear(xidata);
406
0
}
407
408
409
/* getting cross-interpreter data */
410
411
static inline void
412
_set_xid_lookup_failure(PyThreadState *tstate, PyObject *obj, const char *msg,
413
                        PyObject *cause)
414
0
{
415
0
    if (msg != NULL) {
416
0
        assert(obj == NULL);
417
0
        set_notshareableerror(tstate, cause, 0, msg);
418
0
    }
419
0
    else if (obj == NULL) {
420
0
        msg = "object does not support cross-interpreter data";
421
0
        set_notshareableerror(tstate, cause, 0, msg);
422
0
    }
423
0
    else {
424
0
        msg = "%R does not support cross-interpreter data";
425
0
        format_notshareableerror(tstate, cause, 0, msg, obj);
426
0
    }
427
0
}
428
429
430
int
431
_PyObject_CheckXIData(PyThreadState *tstate, PyObject *obj)
432
0
{
433
0
    dlcontext_t ctx;
434
0
    if (get_lookup_context(tstate, &ctx) < 0) {
435
0
        return -1;
436
0
    }
437
0
    _PyXIData_getdata_t getdata = lookup_getdata(&ctx, obj);
438
0
    if (getdata.basic == NULL && getdata.fallback == NULL) {
439
0
        if (!_PyErr_Occurred(tstate)) {
440
0
            _set_xid_lookup_failure(tstate, obj, NULL, NULL);
441
0
        }
442
0
        return -1;
443
0
    }
444
0
    return 0;
445
0
}
446
447
static int
448
_check_xidata(PyThreadState *tstate, _PyXIData_t *xidata)
449
0
{
450
    // xidata->data can be anything, including NULL, so we don't check it.
451
452
    // xidata->obj may be NULL, so we don't check it.
453
454
0
    if (_PyXIData_INTERPID(xidata) < 0) {
455
0
        PyErr_SetString(PyExc_SystemError, "missing interp");
456
0
        return -1;
457
0
    }
458
459
0
    if (xidata->new_object == NULL) {
460
0
        PyErr_SetString(PyExc_SystemError, "missing new_object func");
461
0
        return -1;
462
0
    }
463
464
    // xidata->free may be NULL, so we don't check it.
465
466
0
    return 0;
467
0
}
468
469
static int
470
_get_xidata(PyThreadState *tstate,
471
            PyObject *obj, xidata_fallback_t fallback, _PyXIData_t *xidata)
472
0
{
473
0
    PyInterpreterState *interp = tstate->interp;
474
475
0
    assert(xidata->data == NULL);
476
0
    assert(xidata->obj == NULL);
477
0
    if (xidata->data != NULL || xidata->obj != NULL) {
478
0
        _PyErr_SetString(tstate, PyExc_ValueError, "xidata not cleared");
479
0
        return -1;
480
0
    }
481
482
    // Call the "getdata" func for the object.
483
0
    dlcontext_t ctx;
484
0
    if (get_lookup_context(tstate, &ctx) < 0) {
485
0
        return -1;
486
0
    }
487
0
    Py_INCREF(obj);
488
0
    _PyXIData_getdata_t getdata = lookup_getdata(&ctx, obj);
489
0
    if (getdata.basic == NULL && getdata.fallback == NULL) {
490
0
        if (PyErr_Occurred()) {
491
0
            Py_DECREF(obj);
492
0
            return -1;
493
0
        }
494
        // Fall back to obj
495
0
        Py_DECREF(obj);
496
0
        if (!_PyErr_Occurred(tstate)) {
497
0
            _set_xid_lookup_failure(tstate, obj, NULL, NULL);
498
0
        }
499
0
        return -1;
500
0
    }
501
0
    int res = getdata.basic != NULL
502
0
        ? getdata.basic(tstate, obj, xidata)
503
0
        : getdata.fallback(tstate, obj, fallback, xidata);
504
0
    Py_DECREF(obj);
505
0
    if (res != 0) {
506
0
        PyObject *cause = _PyErr_GetRaisedException(tstate);
507
0
        assert(cause != NULL);
508
0
        _set_xid_lookup_failure(tstate, obj, NULL, cause);
509
0
        Py_XDECREF(cause);
510
0
        return -1;
511
0
    }
512
513
    // Fill in the blanks and validate the result.
514
0
    _PyXIData_INTERPID(xidata) = PyInterpreterState_GetID(interp);
515
0
    if (_check_xidata(tstate, xidata) != 0) {
516
0
        (void)_PyXIData_Release(xidata);
517
0
        return -1;
518
0
    }
519
520
0
    return 0;
521
0
}
522
523
int
524
_PyObject_GetXIDataNoFallback(PyThreadState *tstate,
525
                              PyObject *obj, _PyXIData_t *xidata)
526
0
{
527
0
    return _get_xidata(tstate, obj, _PyXIDATA_XIDATA_ONLY, xidata);
528
0
}
529
530
int
531
_PyObject_GetXIData(PyThreadState *tstate,
532
                    PyObject *obj, xidata_fallback_t fallback,
533
                    _PyXIData_t *xidata)
534
0
{
535
0
    switch (fallback) {
536
0
        case _PyXIDATA_XIDATA_ONLY:
537
0
            return _get_xidata(tstate, obj, fallback, xidata);
538
0
        case _PyXIDATA_FULL_FALLBACK:
539
0
            if (_get_xidata(tstate, obj, fallback, xidata) == 0) {
540
0
                return 0;
541
0
            }
542
0
            PyObject *exc = _PyErr_GetRaisedException(tstate);
543
0
            if (PyFunction_Check(obj)) {
544
0
                if (_PyFunction_GetXIData(tstate, obj, xidata) == 0) {
545
0
                    Py_DECREF(exc);
546
0
                    return 0;
547
0
                }
548
0
                _PyErr_Clear(tstate);
549
0
            }
550
            // We could try _PyMarshal_GetXIData() but we won't for now.
551
0
            if (_PyPickle_GetXIData(tstate, obj, xidata) == 0) {
552
0
                Py_DECREF(exc);
553
0
                return 0;
554
0
            }
555
            // Raise the original exception.
556
0
            _PyErr_SetRaisedException(tstate, exc);
557
0
            return -1;
558
0
        default:
559
#ifdef Py_DEBUG
560
            Py_FatalError("unsupported xidata fallback option");
561
#endif
562
0
            _PyErr_SetString(tstate, PyExc_SystemError,
563
0
                             "unsupported xidata fallback option");
564
0
            return -1;
565
0
    }
566
0
}
567
568
569
/* pickle C-API */
570
571
/* Per-interpreter cache for pickle.dumps and pickle.loads.
572
 *
573
 * Each interpreter has its own cache in _PyXI_state_t.pickle, preserving
574
 * interpreter isolation.  The cache is populated lazily on first use and
575
 * cleared during interpreter finalization in _Py_xi_state_fini().
576
 *
577
 * Note: the cached references are captured at first use and not invalidated
578
 * on module reload.  This matches the caching pattern used elsewhere in
579
 * CPython (e.g. arraymodule.c, _decimal.c). */
580
581
static PyObject *
582
_get_pickle_dumps(PyThreadState *tstate)
583
0
{
584
0
    _PyXI_state_t *state = _PyXI_GET_STATE(tstate->interp);
585
0
    PyObject *dumps = state->pickle.dumps;
586
0
    if (dumps != NULL) {
587
0
        return dumps;
588
0
    }
589
0
    dumps = PyImport_ImportModuleAttrString("pickle", "dumps");
590
0
    if (dumps == NULL) {
591
0
        return NULL;
592
0
    }
593
0
    state->pickle.dumps = dumps;  // owns the reference
594
0
    return dumps;
595
0
}
596
597
static PyObject *
598
_get_pickle_loads(PyThreadState *tstate)
599
0
{
600
0
    _PyXI_state_t *state = _PyXI_GET_STATE(tstate->interp);
601
0
    PyObject *loads = state->pickle.loads;
602
0
    if (loads != NULL) {
603
0
        return loads;
604
0
    }
605
0
    loads = PyImport_ImportModuleAttrString("pickle", "loads");
606
0
    if (loads == NULL) {
607
0
        return NULL;
608
0
    }
609
0
    state->pickle.loads = loads;  // owns the reference
610
0
    return loads;
611
0
}
612
613
struct _pickle_context {
614
    PyThreadState *tstate;
615
};
616
617
static PyObject *
618
_PyPickle_Dumps(struct _pickle_context *ctx, PyObject *obj)
619
0
{
620
0
    PyObject *dumps = _get_pickle_dumps(ctx->tstate);
621
0
    if (dumps == NULL) {
622
0
        return NULL;
623
0
    }
624
    // dumps is a borrowed reference from the cache.
625
0
    return PyObject_CallOneArg(dumps, obj);
626
0
}
627
628
629
struct _unpickle_context {
630
    PyThreadState *tstate;
631
    // We only special-case the __main__ module,
632
    // since other modules behave consistently.
633
    struct sync_module main;
634
};
635
636
static void
637
_unpickle_context_clear(struct _unpickle_context *ctx)
638
0
{
639
0
    sync_module_clear(&ctx->main);
640
0
}
641
642
static int
643
check_missing___main___attr(PyObject *exc)
644
0
{
645
0
    assert(!PyErr_Occurred());
646
0
    if (!PyErr_GivenExceptionMatches(exc, PyExc_AttributeError)) {
647
0
        return 0;
648
0
    }
649
650
    // Get the error message.
651
0
    PyObject *args = PyException_GetArgs(exc);
652
0
    if (args == NULL || args == Py_None || PyObject_Size(args) < 1) {
653
0
        Py_XDECREF(args);
654
0
        assert(!PyErr_Occurred());
655
0
        return 0;
656
0
    }
657
0
    PyObject *msgobj = args;
658
0
    if (!PyUnicode_Check(msgobj)) {
659
0
        msgobj = PySequence_GetItem(args, 0);
660
0
        Py_DECREF(args);
661
0
        if (msgobj == NULL) {
662
0
            PyErr_Clear();
663
0
            return 0;
664
0
        }
665
0
    }
666
0
    const char *err = PyUnicode_AsUTF8(msgobj);
667
0
    if (err == NULL) {
668
0
        PyErr_Clear();
669
0
        Py_DECREF(msgobj);
670
0
        return 0;
671
0
    }
672
673
    // Check if it's a missing __main__ attr.
674
0
    int cmp = strncmp(err, "module '__main__' has no attribute '", 36);
675
0
    Py_DECREF(msgobj);
676
0
    return cmp == 0;
677
0
}
678
679
static PyObject *
680
_PyPickle_Loads(struct _unpickle_context *ctx, PyObject *pickled)
681
0
{
682
0
    PyThreadState *tstate = ctx->tstate;
683
684
0
    PyObject *exc = NULL;
685
    // loads is a borrowed reference from the per-interpreter cache.
686
0
    PyObject *loads = _get_pickle_loads(tstate);
687
0
    if (loads == NULL) {
688
0
        return NULL;
689
0
    }
690
691
    // Make an initial attempt to unpickle.
692
0
    PyObject *obj = PyObject_CallOneArg(loads, pickled);
693
0
    if (obj != NULL) {
694
0
        goto finally;
695
0
    }
696
0
    assert(_PyErr_Occurred(tstate));
697
0
    if (ctx == NULL) {
698
0
        goto finally;
699
0
    }
700
0
    exc = _PyErr_GetRaisedException(tstate);
701
0
    if (!check_missing___main___attr(exc)) {
702
0
        goto finally;
703
0
    }
704
705
    // Temporarily swap in a fake __main__ loaded from the original
706
    // file and cached.  Note that functions will use the cached ns
707
    // for __globals__, // not the actual module.
708
0
    if (ensure_isolated_main(tstate, &ctx->main) < 0) {
709
0
        goto finally;
710
0
    }
711
0
    if (apply_isolated_main(tstate, &ctx->main) < 0) {
712
0
        goto finally;
713
0
    }
714
715
    // Try to unpickle once more.
716
0
    obj = PyObject_CallOneArg(loads, pickled);
717
0
    restore_main(tstate, &ctx->main);
718
0
    if (obj == NULL) {
719
0
        goto finally;
720
0
    }
721
0
    Py_CLEAR(exc);
722
723
0
finally:
724
0
    if (exc != NULL) {
725
0
        if (_PyErr_Occurred(tstate)) {
726
0
            sync_module_capture_exc(tstate, &ctx->main);
727
0
        }
728
        // We restore the original exception.
729
        // It might make sense to chain it (__context__).
730
0
        _PyErr_SetRaisedException(tstate, exc);
731
0
    }
732
0
    return obj;
733
0
}
734
735
736
/* pickle wrapper */
737
738
struct _pickle_xid_context {
739
    // __main__.__file__
740
    struct {
741
        const char *utf8;
742
        size_t len;
743
        char _utf8[MAXPATHLEN+1];
744
    } mainfile;
745
};
746
747
static int
748
_set_pickle_xid_context(PyThreadState *tstate, struct _pickle_xid_context *ctx)
749
0
{
750
    // Set mainfile if possible.
751
0
    Py_ssize_t len = _Py_GetMainfile(ctx->mainfile._utf8, MAXPATHLEN);
752
0
    if (len < 0) {
753
        // For now we ignore any exceptions.
754
0
        PyErr_Clear();
755
0
    }
756
0
    else if (len > 0) {
757
0
        ctx->mainfile.utf8 = ctx->mainfile._utf8;
758
0
        ctx->mainfile.len = (size_t)len;
759
0
    }
760
761
0
    return 0;
762
0
}
763
764
765
struct _shared_pickle_data {
766
    _PyBytes_data_t pickled;  // Must be first if we use _PyBytes_FromXIData().
767
    struct _pickle_xid_context ctx;
768
};
769
770
PyObject *
771
_PyPickle_LoadFromXIData(_PyXIData_t *xidata)
772
0
{
773
0
    PyThreadState *tstate = _PyThreadState_GET();
774
0
    struct _shared_pickle_data *shared =
775
0
                            (struct _shared_pickle_data *)xidata->data;
776
    // We avoid copying the pickled data by wrapping it in a memoryview.
777
    // The alternative is to get a bytes object using _PyBytes_FromXIData().
778
0
    PyObject *pickled = PyMemoryView_FromMemory(
779
0
            (char *)shared->pickled.bytes, shared->pickled.len, PyBUF_READ);
780
0
    if (pickled == NULL) {
781
0
        return NULL;
782
0
    }
783
784
    // Unpickle the object.
785
0
    struct _unpickle_context ctx = {
786
0
        .tstate = tstate,
787
0
        .main = {
788
0
            .filename = shared->ctx.mainfile.utf8,
789
0
        },
790
0
    };
791
0
    PyObject *obj = _PyPickle_Loads(&ctx, pickled);
792
0
    Py_DECREF(pickled);
793
0
    _unpickle_context_clear(&ctx);
794
0
    if (obj == NULL) {
795
0
        PyObject *cause = _PyErr_GetRaisedException(tstate);
796
0
        assert(cause != NULL);
797
0
        _set_xid_lookup_failure(
798
0
                    tstate, NULL, "object could not be unpickled", cause);
799
0
        Py_DECREF(cause);
800
0
    }
801
0
    return obj;
802
0
}
803
804
805
int
806
_PyPickle_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
807
0
{
808
    // Pickle the object.
809
0
    struct _pickle_context ctx = {
810
0
        .tstate = tstate,
811
0
    };
812
0
    PyObject *bytes = _PyPickle_Dumps(&ctx, obj);
813
0
    if (bytes == NULL) {
814
0
        PyObject *cause = _PyErr_GetRaisedException(tstate);
815
0
        assert(cause != NULL);
816
0
        _set_xid_lookup_failure(
817
0
                    tstate, NULL, "object could not be pickled", cause);
818
0
        Py_DECREF(cause);
819
0
        return -1;
820
0
    }
821
822
    // If we had an "unwrapper" mechnanism, we could call
823
    // _PyObject_GetXIData() on the bytes object directly and add
824
    // a simple unwrapper to call pickle.loads() on the bytes.
825
0
    size_t size = sizeof(struct _shared_pickle_data);
826
0
    struct _shared_pickle_data *shared =
827
0
            (struct _shared_pickle_data *)_PyBytes_GetXIDataWrapped(
828
0
                    tstate, bytes, size, _PyPickle_LoadFromXIData, xidata);
829
0
    Py_DECREF(bytes);
830
0
    if (shared == NULL) {
831
0
        return -1;
832
0
    }
833
834
    // If it mattered, we could skip getting __main__.__file__
835
    // when "__main__" doesn't show up in the pickle bytes.
836
0
    if (_set_pickle_xid_context(tstate, &shared->ctx) < 0) {
837
0
        _xidata_clear(xidata);
838
0
        return -1;
839
0
    }
840
841
0
    return 0;
842
0
}
843
844
845
/* marshal wrapper */
846
847
PyObject *
848
_PyMarshal_ReadObjectFromXIData(_PyXIData_t *xidata)
849
0
{
850
0
    PyThreadState *tstate = _PyThreadState_GET();
851
0
    _PyBytes_data_t *shared = (_PyBytes_data_t *)xidata->data;
852
0
    PyObject *obj = PyMarshal_ReadObjectFromString(shared->bytes, shared->len);
853
0
    if (obj == NULL) {
854
0
        PyObject *cause = _PyErr_GetRaisedException(tstate);
855
0
        assert(cause != NULL);
856
0
        _set_xid_lookup_failure(
857
0
                    tstate, NULL, "object could not be unmarshalled", cause);
858
0
        Py_DECREF(cause);
859
0
        return NULL;
860
0
    }
861
0
    return obj;
862
0
}
863
864
int
865
_PyMarshal_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
866
0
{
867
0
    PyObject *bytes = PyMarshal_WriteObjectToString(obj, Py_MARSHAL_VERSION);
868
0
    if (bytes == NULL) {
869
0
        PyObject *cause = _PyErr_GetRaisedException(tstate);
870
0
        assert(cause != NULL);
871
0
        _set_xid_lookup_failure(
872
0
                    tstate, NULL, "object could not be marshalled", cause);
873
0
        Py_DECREF(cause);
874
0
        return -1;
875
0
    }
876
0
    size_t size = sizeof(_PyBytes_data_t);
877
0
    _PyBytes_data_t *shared = _PyBytes_GetXIDataWrapped(
878
0
            tstate, bytes, size, _PyMarshal_ReadObjectFromXIData, xidata);
879
0
    Py_DECREF(bytes);
880
0
    if (shared == NULL) {
881
0
        return -1;
882
0
    }
883
0
    return 0;
884
0
}
885
886
887
/* script wrapper */
888
889
static int
890
verify_script(PyThreadState *tstate, PyCodeObject *co, int checked, int pure)
891
0
{
892
    // Make sure it isn't a closure and (optionally) doesn't use globals.
893
0
    PyObject *builtins = NULL;
894
0
    if (pure) {
895
0
        builtins = _PyEval_GetBuiltins(tstate);
896
0
        assert(builtins != NULL);
897
0
    }
898
0
    if (checked) {
899
0
        assert(_PyCode_VerifyStateless(tstate, co, NULL, NULL, builtins) == 0);
900
0
    }
901
0
    else if (_PyCode_VerifyStateless(tstate, co, NULL, NULL, builtins) < 0) {
902
0
        return -1;
903
0
    }
904
    // Make sure it doesn't have args.
905
0
    if (co->co_argcount > 0
906
0
        || co->co_posonlyargcount > 0
907
0
        || co->co_kwonlyargcount > 0
908
0
        || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS))
909
0
    {
910
0
        _PyErr_SetString(tstate, PyExc_ValueError,
911
0
                         "code with args not supported");
912
0
        return -1;
913
0
    }
914
    // Make sure it doesn't return anything.
915
0
    if (!_PyCode_ReturnsOnlyNone(co)) {
916
0
        _PyErr_SetString(tstate, PyExc_ValueError,
917
0
                         "code that returns a value is not a script");
918
0
        return -1;
919
0
    }
920
0
    return 0;
921
0
}
922
923
static int
924
get_script_xidata(PyThreadState *tstate, PyObject *obj, int pure,
925
                  _PyXIData_t *xidata)
926
0
{
927
    // Get the corresponding code object.
928
0
    PyObject *code = NULL;
929
0
    int checked = 0;
930
0
    if (PyCode_Check(obj)) {
931
0
        code = obj;
932
0
        Py_INCREF(code);
933
0
    }
934
0
    else if (PyFunction_Check(obj)) {
935
0
        code = PyFunction_GET_CODE(obj);
936
0
        assert(code != NULL);
937
0
        Py_INCREF(code);
938
0
        if (pure) {
939
0
            if (_PyFunction_VerifyStateless(tstate, obj) < 0) {
940
0
                goto error;
941
0
            }
942
0
            checked = 1;
943
0
        }
944
0
    }
945
0
    else {
946
0
        const char *filename = "<script>";
947
0
        int optimize = 0;
948
0
        PyCompilerFlags cf = _PyCompilerFlags_INIT;
949
0
        cf.cf_flags = PyCF_SOURCE_IS_UTF8;
950
0
        PyObject *ref = NULL;
951
0
        const char *script = _Py_SourceAsString(obj, "???", "???", &cf, &ref);
952
0
        if (script == NULL) {
953
0
            if (!_PyObject_SupportedAsScript(obj)) {
954
                // We discard the raised exception.
955
0
                _PyErr_Format(tstate, PyExc_TypeError,
956
0
                              "unsupported script %R", obj);
957
0
            }
958
0
            goto error;
959
0
        }
960
#ifdef Py_GIL_DISABLED
961
        // Don't immortalize code constants to avoid memory leaks.
962
        ((_PyThreadStateImpl *)tstate)->suppress_co_const_immortalization++;
963
#endif
964
0
        code = Py_CompileStringExFlags(
965
0
                    script, filename, Py_file_input, &cf, optimize);
966
#ifdef Py_GIL_DISABLED
967
        ((_PyThreadStateImpl *)tstate)->suppress_co_const_immortalization--;
968
#endif
969
0
        Py_XDECREF(ref);
970
0
        if (code == NULL) {
971
0
            goto error;
972
0
        }
973
        // Compiled text can't have args or any return statements,
974
        // nor be a closure.  It can use globals though.
975
0
        if (!pure) {
976
            // We don't need to check for globals either.
977
0
            checked = 1;
978
0
        }
979
0
    }
980
981
    // Make sure it's actually a script.
982
0
    if (verify_script(tstate, (PyCodeObject *)code, checked, pure) < 0) {
983
0
        goto error;
984
0
    }
985
986
    // Convert the code object.
987
0
    int res = _PyCode_GetXIData(tstate, code, xidata);
988
0
    Py_DECREF(code);
989
0
    if (res < 0) {
990
0
        return -1;
991
0
    }
992
0
    return 0;
993
994
0
error:
995
0
    Py_XDECREF(code);
996
0
    PyObject *cause = _PyErr_GetRaisedException(tstate);
997
0
    assert(cause != NULL);
998
0
    _set_xid_lookup_failure(
999
0
                tstate, NULL, "object not a valid script", cause);
1000
0
    Py_DECREF(cause);
1001
0
    return -1;
1002
0
}
1003
1004
int
1005
_PyCode_GetScriptXIData(PyThreadState *tstate,
1006
                        PyObject *obj, _PyXIData_t *xidata)
1007
0
{
1008
0
    return get_script_xidata(tstate, obj, 0, xidata);
1009
0
}
1010
1011
int
1012
_PyCode_GetPureScriptXIData(PyThreadState *tstate,
1013
                            PyObject *obj, _PyXIData_t *xidata)
1014
0
{
1015
0
    return get_script_xidata(tstate, obj, 1, xidata);
1016
0
}
1017
1018
1019
/* using cross-interpreter data */
1020
1021
PyObject *
1022
_PyXIData_NewObject(_PyXIData_t *xidata)
1023
0
{
1024
0
    return xidata->new_object(xidata);
1025
0
}
1026
1027
static int
1028
_call_clear_xidata(void *data)
1029
0
{
1030
0
    _xidata_clear((_PyXIData_t *)data);
1031
0
    return 0;
1032
0
}
1033
1034
static int
1035
_xidata_release(_PyXIData_t *xidata, int rawfree)
1036
0
{
1037
0
    if ((xidata->data == NULL || xidata->free == NULL) && xidata->obj == NULL) {
1038
        // Nothing to release!
1039
0
        if (rawfree) {
1040
0
            PyMem_RawFree(xidata);
1041
0
        }
1042
0
        else {
1043
0
            xidata->data = NULL;
1044
0
        }
1045
0
        return 0;
1046
0
    }
1047
1048
    // Switch to the original interpreter.
1049
0
    PyInterpreterState *interp = _PyInterpreterState_LookUpID(
1050
0
                                        _PyXIData_INTERPID(xidata));
1051
0
    if (interp == NULL) {
1052
        // The interpreter was already destroyed.
1053
        // This function shouldn't have been called.
1054
        // XXX Someone leaked some memory...
1055
0
        assert(PyErr_Occurred());
1056
0
        if (rawfree) {
1057
0
            PyMem_RawFree(xidata);
1058
0
        }
1059
0
        return -1;
1060
0
    }
1061
1062
    // "Release" the data and/or the object.
1063
0
    if (rawfree) {
1064
0
        return _Py_CallInInterpreterAndRawFree(interp, _call_clear_xidata, xidata);
1065
0
    }
1066
0
    else {
1067
0
        return _Py_CallInInterpreter(interp, _call_clear_xidata, xidata);
1068
0
    }
1069
0
}
1070
1071
int
1072
_PyXIData_Release(_PyXIData_t *xidata)
1073
0
{
1074
0
    return _xidata_release(xidata, 0);
1075
0
}
1076
1077
int
1078
_PyXIData_ReleaseAndRawFree(_PyXIData_t *xidata)
1079
0
{
1080
0
    return _xidata_release(xidata, 1);
1081
0
}
1082
1083
1084
/*************************/
1085
/* convenience utilities */
1086
/*************************/
1087
1088
static char *
1089
_copy_string_obj_raw(PyObject *strobj, Py_ssize_t *p_size)
1090
0
{
1091
0
    Py_ssize_t size = -1;
1092
0
    const char *str = PyUnicode_AsUTF8AndSize(strobj, &size);
1093
0
    if (str == NULL) {
1094
0
        return NULL;
1095
0
    }
1096
1097
0
    if (size != (Py_ssize_t)strlen(str)) {
1098
0
        PyErr_SetString(PyExc_ValueError, "found embedded NULL character");
1099
0
        return NULL;
1100
0
    }
1101
1102
0
    char *copied = PyMem_RawMalloc(size+1);
1103
0
    if (copied == NULL) {
1104
0
        PyErr_NoMemory();
1105
0
        return NULL;
1106
0
    }
1107
0
    strcpy(copied, str);
1108
0
    if (p_size != NULL) {
1109
0
        *p_size = size;
1110
0
    }
1111
0
    return copied;
1112
0
}
1113
1114
1115
static int
1116
_convert_exc_to_TracebackException(PyObject *exc, PyObject **p_tbexc)
1117
0
{
1118
0
    PyObject *args = NULL;
1119
0
    PyObject *kwargs = NULL;
1120
0
    PyObject *create = NULL;
1121
1122
    // This is inspired by _PyErr_Display().
1123
0
    PyObject *tbexc_type = PyImport_ImportModuleAttrString(
1124
0
        "traceback",
1125
0
        "TracebackException");
1126
0
    if (tbexc_type == NULL) {
1127
0
        return -1;
1128
0
    }
1129
0
    create = PyObject_GetAttrString(tbexc_type, "from_exception");
1130
0
    Py_DECREF(tbexc_type);
1131
0
    if (create == NULL) {
1132
0
        return -1;
1133
0
    }
1134
1135
0
    args = PyTuple_Pack(1, exc);
1136
0
    if (args == NULL) {
1137
0
        goto error;
1138
0
    }
1139
1140
0
    kwargs = PyDict_New();
1141
0
    if (kwargs == NULL) {
1142
0
        goto error;
1143
0
    }
1144
0
    if (PyDict_SetItemString(kwargs, "save_exc_type", Py_False) < 0) {
1145
0
        goto error;
1146
0
    }
1147
0
    if (PyDict_SetItemString(kwargs, "lookup_lines", Py_False) < 0) {
1148
0
        goto error;
1149
0
    }
1150
1151
0
    PyObject *tbexc = PyObject_Call(create, args, kwargs);
1152
0
    if (tbexc == NULL) {
1153
0
        goto error;
1154
0
    }
1155
0
    Py_DECREF(args);
1156
0
    Py_DECREF(kwargs);
1157
0
    Py_DECREF(create);
1158
1159
0
    *p_tbexc = tbexc;
1160
0
    return 0;
1161
1162
0
error:
1163
0
    Py_XDECREF(args);
1164
0
    Py_XDECREF(kwargs);
1165
0
    Py_XDECREF(create);
1166
0
    return -1;
1167
0
}
1168
1169
// We accommodate backports here.
1170
#ifndef _Py_EMPTY_STR
1171
0
# define _Py_EMPTY_STR &_Py_STR(empty)
1172
#endif
1173
1174
static const char *
1175
_format_TracebackException(PyObject *tbexc)
1176
0
{
1177
0
    PyObject *lines = PyObject_CallMethod(tbexc, "format", NULL);
1178
0
    if (lines == NULL) {
1179
0
        return NULL;
1180
0
    }
1181
0
    assert(_Py_EMPTY_STR != NULL);
1182
0
    PyObject *formatted_obj = PyUnicode_Join(_Py_EMPTY_STR, lines);
1183
0
    Py_DECREF(lines);
1184
0
    if (formatted_obj == NULL) {
1185
0
        return NULL;
1186
0
    }
1187
1188
0
    Py_ssize_t size = -1;
1189
0
    char *formatted = _copy_string_obj_raw(formatted_obj, &size);
1190
0
    Py_DECREF(formatted_obj);
1191
0
    if (formatted == NULL || size == 0) {
1192
0
        return formatted;
1193
0
    }
1194
0
    assert(formatted[size] == '\0');
1195
    // Remove a trailing newline if needed.
1196
0
    if (formatted[size-1] == '\n') {
1197
0
        formatted[size-1] = '\0';
1198
0
    }
1199
0
    return formatted;
1200
0
}
1201
1202
1203
static int
1204
_release_xid_data(_PyXIData_t *xidata, int rawfree)
1205
0
{
1206
0
    PyObject *exc = PyErr_GetRaisedException();
1207
0
    int res = rawfree
1208
0
        ? _PyXIData_ReleaseAndRawFree(xidata)
1209
0
        : _PyXIData_Release(xidata);
1210
0
    if (res < 0) {
1211
        /* The owning interpreter is already destroyed. */
1212
0
        _PyXIData_Clear(NULL, xidata);
1213
        // XXX Emit a warning?
1214
0
        PyErr_Clear();
1215
0
    }
1216
0
    PyErr_SetRaisedException(exc);
1217
0
    return res;
1218
0
}
1219
1220
1221
/***********************/
1222
/* exception snapshots */
1223
/***********************/
1224
1225
static int
1226
_excinfo_init_type_from_exception(struct _excinfo_type *info, PyObject *exc)
1227
0
{
1228
    /* Note that this copies directly rather than into an intermediate
1229
       struct and does not clear on error.  If we need that then we
1230
       should have a separate function to wrap this one
1231
       and do all that there. */
1232
0
    PyObject *strobj = NULL;
1233
1234
0
    PyTypeObject *type = Py_TYPE(exc);
1235
0
    if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
1236
0
        assert(_Py_IsImmortal((PyObject *)type));
1237
0
        info->builtin = type;
1238
0
    }
1239
0
    else {
1240
        // Only builtin types are preserved.
1241
0
        info->builtin = NULL;
1242
0
    }
1243
1244
    // __name__
1245
0
    strobj = PyType_GetName(type);
1246
0
    if (strobj == NULL) {
1247
0
        return -1;
1248
0
    }
1249
0
    info->name = _copy_string_obj_raw(strobj, NULL);
1250
0
    Py_DECREF(strobj);
1251
0
    if (info->name == NULL) {
1252
0
        return -1;
1253
0
    }
1254
1255
    // __qualname__
1256
0
    strobj = PyType_GetQualName(type);
1257
0
    if (strobj == NULL) {
1258
0
        return -1;
1259
0
    }
1260
0
    info->qualname = _copy_string_obj_raw(strobj, NULL);
1261
0
    Py_DECREF(strobj);
1262
0
    if (info->qualname == NULL) {
1263
0
        return -1;
1264
0
    }
1265
1266
    // __module__
1267
0
    strobj = PyType_GetModuleName(type);
1268
0
    if (strobj == NULL) {
1269
0
        return -1;
1270
0
    }
1271
0
    info->module = _copy_string_obj_raw(strobj, NULL);
1272
0
    Py_DECREF(strobj);
1273
0
    if (info->module == NULL) {
1274
0
        return -1;
1275
0
    }
1276
1277
0
    return 0;
1278
0
}
1279
1280
static int
1281
_excinfo_init_type_from_object(struct _excinfo_type *info, PyObject *exctype)
1282
0
{
1283
0
    PyObject *strobj = NULL;
1284
1285
    // __name__
1286
0
    strobj = PyObject_GetAttrString(exctype, "__name__");
1287
0
    if (strobj == NULL) {
1288
0
        return -1;
1289
0
    }
1290
0
    info->name = _copy_string_obj_raw(strobj, NULL);
1291
0
    Py_DECREF(strobj);
1292
0
    if (info->name == NULL) {
1293
0
        return -1;
1294
0
    }
1295
1296
    // __qualname__
1297
0
    strobj = PyObject_GetAttrString(exctype, "__qualname__");
1298
0
    if (strobj == NULL) {
1299
0
        return -1;
1300
0
    }
1301
0
    info->qualname = _copy_string_obj_raw(strobj, NULL);
1302
0
    Py_DECREF(strobj);
1303
0
    if (info->qualname == NULL) {
1304
0
        return -1;
1305
0
    }
1306
1307
    // __module__
1308
0
    strobj = PyObject_GetAttrString(exctype, "__module__");
1309
0
    if (strobj == NULL) {
1310
0
        return -1;
1311
0
    }
1312
0
    info->module = _copy_string_obj_raw(strobj, NULL);
1313
0
    Py_DECREF(strobj);
1314
0
    if (info->module == NULL) {
1315
0
        return -1;
1316
0
    }
1317
1318
0
    return 0;
1319
0
}
1320
1321
static void
1322
_excinfo_clear_type(struct _excinfo_type *info)
1323
0
{
1324
0
    if (info->builtin != NULL) {
1325
0
        assert(info->builtin->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN);
1326
0
        assert(_Py_IsImmortal((PyObject *)info->builtin));
1327
0
    }
1328
0
    if (info->name != NULL) {
1329
0
        PyMem_RawFree((void *)info->name);
1330
0
    }
1331
0
    if (info->qualname != NULL) {
1332
0
        PyMem_RawFree((void *)info->qualname);
1333
0
    }
1334
0
    if (info->module != NULL) {
1335
0
        PyMem_RawFree((void *)info->module);
1336
0
    }
1337
0
    *info = (struct _excinfo_type){NULL};
1338
0
}
1339
1340
static void
1341
_excinfo_normalize_type(struct _excinfo_type *info,
1342
                        const char **p_module, const char **p_qualname)
1343
0
{
1344
0
    if (info->name == NULL) {
1345
0
        assert(info->builtin == NULL);
1346
0
        assert(info->qualname == NULL);
1347
0
        assert(info->module == NULL);
1348
        // This is inspired by TracebackException.format_exception_only().
1349
0
        *p_module = NULL;
1350
0
        *p_qualname = NULL;
1351
0
        return;
1352
0
    }
1353
1354
0
    const char *module = info->module;
1355
0
    const char *qualname = info->qualname;
1356
0
    if (qualname == NULL) {
1357
0
        qualname = info->name;
1358
0
    }
1359
0
    assert(module != NULL);
1360
0
    if (strcmp(module, "builtins") == 0) {
1361
0
        module = NULL;
1362
0
    }
1363
0
    else if (strcmp(module, "__main__") == 0) {
1364
0
        module = NULL;
1365
0
    }
1366
0
    *p_qualname = qualname;
1367
0
    *p_module = module;
1368
0
}
1369
1370
static int
1371
excinfo_is_set(_PyXI_excinfo *info)
1372
0
{
1373
0
    return info->type.name != NULL || info->msg != NULL;
1374
0
}
1375
1376
static void
1377
_PyXI_excinfo_clear(_PyXI_excinfo *info)
1378
0
{
1379
0
    _excinfo_clear_type(&info->type);
1380
0
    if (info->msg != NULL) {
1381
0
        PyMem_RawFree((void *)info->msg);
1382
0
    }
1383
0
    if (info->errdisplay != NULL) {
1384
0
        PyMem_RawFree((void *)info->errdisplay);
1385
0
    }
1386
0
    *info = (_PyXI_excinfo){{NULL}};
1387
0
}
1388
1389
PyObject *
1390
_PyXI_excinfo_format(_PyXI_excinfo *info)
1391
0
{
1392
0
    const char *module, *qualname;
1393
0
    _excinfo_normalize_type(&info->type, &module, &qualname);
1394
0
    if (qualname != NULL) {
1395
0
        if (module != NULL) {
1396
0
            if (info->msg != NULL) {
1397
0
                return PyUnicode_FromFormat("%s.%s: %s",
1398
0
                                            module, qualname, info->msg);
1399
0
            }
1400
0
            else {
1401
0
                return PyUnicode_FromFormat("%s.%s", module, qualname);
1402
0
            }
1403
0
        }
1404
0
        else {
1405
0
            if (info->msg != NULL) {
1406
0
                return PyUnicode_FromFormat("%s: %s", qualname, info->msg);
1407
0
            }
1408
0
            else {
1409
0
                return PyUnicode_FromString(qualname);
1410
0
            }
1411
0
        }
1412
0
    }
1413
0
    else if (info->msg != NULL) {
1414
0
        return PyUnicode_FromString(info->msg);
1415
0
    }
1416
0
    else {
1417
0
        Py_RETURN_NONE;
1418
0
    }
1419
0
}
1420
1421
static const char *
1422
_PyXI_excinfo_InitFromException(_PyXI_excinfo *info, PyObject *exc)
1423
0
{
1424
0
    assert(exc != NULL);
1425
1426
0
    if (PyErr_GivenExceptionMatches(exc, PyExc_MemoryError)) {
1427
0
        _PyXI_excinfo_clear(info);
1428
0
        return NULL;
1429
0
    }
1430
0
    const char *failure = NULL;
1431
1432
0
    if (_excinfo_init_type_from_exception(&info->type, exc) < 0) {
1433
0
        failure = "error while initializing exception type snapshot";
1434
0
        goto error;
1435
0
    }
1436
1437
    // Extract the exception message.
1438
0
    PyObject *msgobj = PyObject_Str(exc);
1439
0
    if (msgobj == NULL) {
1440
0
        failure = "error while formatting exception";
1441
0
        goto error;
1442
0
    }
1443
0
    info->msg = _copy_string_obj_raw(msgobj, NULL);
1444
0
    Py_DECREF(msgobj);
1445
0
    if (info->msg == NULL) {
1446
0
        failure = "error while copying exception message";
1447
0
        goto error;
1448
0
    }
1449
1450
    // Pickle a traceback.TracebackException.
1451
0
    PyObject *tbexc = NULL;
1452
0
    if (_convert_exc_to_TracebackException(exc, &tbexc) < 0) {
1453
#ifdef Py_DEBUG
1454
        PyErr_FormatUnraisable("Exception ignored while creating TracebackException");
1455
#endif
1456
0
        PyErr_Clear();
1457
0
    }
1458
0
    else {
1459
0
        info->errdisplay = _format_TracebackException(tbexc);
1460
0
        Py_DECREF(tbexc);
1461
0
        if (info->errdisplay == NULL) {
1462
#ifdef Py_DEBUG
1463
            PyErr_FormatUnraisable("Exception ignored while formatting TracebackException");
1464
#endif
1465
0
            PyErr_Clear();
1466
0
        }
1467
0
    }
1468
1469
0
    return NULL;
1470
1471
0
error:
1472
0
    assert(failure != NULL);
1473
0
    _PyXI_excinfo_clear(info);
1474
0
    return failure;
1475
0
}
1476
1477
static const char *
1478
_PyXI_excinfo_InitFromObject(_PyXI_excinfo *info, PyObject *obj)
1479
0
{
1480
0
    const char *failure = NULL;
1481
1482
0
    PyObject *exctype = PyObject_GetAttrString(obj, "type");
1483
0
    if (exctype == NULL) {
1484
0
        failure = "exception snapshot missing 'type' attribute";
1485
0
        goto error;
1486
0
    }
1487
0
    int res = _excinfo_init_type_from_object(&info->type, exctype);
1488
0
    Py_DECREF(exctype);
1489
0
    if (res < 0) {
1490
0
        failure = "error while initializing exception type snapshot";
1491
0
        goto error;
1492
0
    }
1493
1494
    // Extract the exception message.
1495
0
    PyObject *msgobj = PyObject_GetAttrString(obj, "msg");
1496
0
    if (msgobj == NULL) {
1497
0
        failure = "exception snapshot missing 'msg' attribute";
1498
0
        goto error;
1499
0
    }
1500
0
    info->msg = _copy_string_obj_raw(msgobj, NULL);
1501
0
    Py_DECREF(msgobj);
1502
0
    if (info->msg == NULL) {
1503
0
        failure = "error while copying exception message";
1504
0
        goto error;
1505
0
    }
1506
1507
    // Pickle a traceback.TracebackException.
1508
0
    PyObject *errdisplay = PyObject_GetAttrString(obj, "errdisplay");
1509
0
    if (errdisplay == NULL) {
1510
0
        failure = "exception snapshot missing 'errdisplay' attribute";
1511
0
        goto error;
1512
0
    }
1513
0
    info->errdisplay = _copy_string_obj_raw(errdisplay, NULL);
1514
0
    Py_DECREF(errdisplay);
1515
0
    if (info->errdisplay == NULL) {
1516
0
        failure = "error while copying exception error display";
1517
0
        goto error;
1518
0
    }
1519
1520
0
    return NULL;
1521
1522
0
error:
1523
0
    assert(failure != NULL);
1524
0
    _PyXI_excinfo_clear(info);
1525
0
    return failure;
1526
0
}
1527
1528
static void
1529
_PyXI_excinfo_Apply(_PyXI_excinfo *info, PyObject *exctype)
1530
0
{
1531
0
    PyObject *tbexc = NULL;
1532
0
    if (info->errdisplay != NULL) {
1533
0
        tbexc = PyUnicode_FromString(info->errdisplay);
1534
0
        if (tbexc == NULL) {
1535
0
            PyErr_Clear();
1536
0
        }
1537
0
        else {
1538
0
            PyErr_SetObject(exctype, tbexc);
1539
0
            Py_DECREF(tbexc);
1540
0
            return;
1541
0
        }
1542
0
    }
1543
1544
0
    PyObject *formatted = _PyXI_excinfo_format(info);
1545
0
    PyErr_SetObject(exctype, formatted);
1546
0
    Py_XDECREF(formatted);
1547
1548
0
    if (tbexc != NULL) {
1549
0
        PyObject *exc = PyErr_GetRaisedException();
1550
0
        if (PyObject_SetAttrString(exc, "_errdisplay", tbexc) < 0) {
1551
#ifdef Py_DEBUG
1552
            PyErr_FormatUnraisable("Exception ignored while "
1553
                                   "setting _errdisplay");
1554
#endif
1555
0
            PyErr_Clear();
1556
0
        }
1557
0
        Py_DECREF(tbexc);
1558
0
        PyErr_SetRaisedException(exc);
1559
0
    }
1560
0
}
1561
1562
static PyObject *
1563
_PyXI_excinfo_TypeAsObject(_PyXI_excinfo *info)
1564
0
{
1565
0
    PyObject *ns = _PyNamespace_New(NULL);
1566
0
    if (ns == NULL) {
1567
0
        return NULL;
1568
0
    }
1569
0
    int empty = 1;
1570
1571
0
    if (info->type.name != NULL) {
1572
0
        PyObject *name = PyUnicode_FromString(info->type.name);
1573
0
        if (name == NULL) {
1574
0
            goto error;
1575
0
        }
1576
0
        int res = PyObject_SetAttrString(ns, "__name__", name);
1577
0
        Py_DECREF(name);
1578
0
        if (res < 0) {
1579
0
            goto error;
1580
0
        }
1581
0
        empty = 0;
1582
0
    }
1583
1584
0
    if (info->type.qualname != NULL) {
1585
0
        PyObject *qualname = PyUnicode_FromString(info->type.qualname);
1586
0
        if (qualname == NULL) {
1587
0
            goto error;
1588
0
        }
1589
0
        int res = PyObject_SetAttrString(ns, "__qualname__", qualname);
1590
0
        Py_DECREF(qualname);
1591
0
        if (res < 0) {
1592
0
            goto error;
1593
0
        }
1594
0
        empty = 0;
1595
0
    }
1596
1597
0
    if (info->type.module != NULL) {
1598
0
        PyObject *module = PyUnicode_FromString(info->type.module);
1599
0
        if (module == NULL) {
1600
0
            goto error;
1601
0
        }
1602
0
        int res = PyObject_SetAttrString(ns, "__module__", module);
1603
0
        Py_DECREF(module);
1604
0
        if (res < 0) {
1605
0
            goto error;
1606
0
        }
1607
0
        empty = 0;
1608
0
    }
1609
1610
0
    if (empty) {
1611
0
        Py_CLEAR(ns);
1612
0
    }
1613
1614
0
    return ns;
1615
1616
0
error:
1617
0
    Py_DECREF(ns);
1618
0
    return NULL;
1619
0
}
1620
1621
static PyObject *
1622
_PyXI_excinfo_AsObject(_PyXI_excinfo *info)
1623
0
{
1624
0
    PyObject *ns = _PyNamespace_New(NULL);
1625
0
    if (ns == NULL) {
1626
0
        return NULL;
1627
0
    }
1628
0
    int res;
1629
1630
0
    PyObject *type = _PyXI_excinfo_TypeAsObject(info);
1631
0
    if (type == NULL) {
1632
0
        if (PyErr_Occurred()) {
1633
0
            goto error;
1634
0
        }
1635
0
        type = Py_NewRef(Py_None);
1636
0
    }
1637
0
    res = PyObject_SetAttrString(ns, "type", type);
1638
0
    Py_DECREF(type);
1639
0
    if (res < 0) {
1640
0
        goto error;
1641
0
    }
1642
1643
0
    PyObject *msg = info->msg != NULL
1644
0
        ? PyUnicode_FromString(info->msg)
1645
0
        : Py_NewRef(Py_None);
1646
0
    if (msg == NULL) {
1647
0
        goto error;
1648
0
    }
1649
0
    res = PyObject_SetAttrString(ns, "msg", msg);
1650
0
    Py_DECREF(msg);
1651
0
    if (res < 0) {
1652
0
        goto error;
1653
0
    }
1654
1655
0
    PyObject *formatted = _PyXI_excinfo_format(info);
1656
0
    if (formatted == NULL) {
1657
0
        goto error;
1658
0
    }
1659
0
    res = PyObject_SetAttrString(ns, "formatted", formatted);
1660
0
    Py_DECREF(formatted);
1661
0
    if (res < 0) {
1662
0
        goto error;
1663
0
    }
1664
1665
0
    if (info->errdisplay != NULL) {
1666
0
        PyObject *tbexc = PyUnicode_FromString(info->errdisplay);
1667
0
        if (tbexc == NULL) {
1668
0
            PyErr_Clear();
1669
0
        }
1670
0
        else {
1671
0
            res = PyObject_SetAttrString(ns, "errdisplay", tbexc);
1672
0
            Py_DECREF(tbexc);
1673
0
            if (res < 0) {
1674
0
                goto error;
1675
0
            }
1676
0
        }
1677
0
    }
1678
1679
0
    return ns;
1680
1681
0
error:
1682
0
    Py_DECREF(ns);
1683
0
    return NULL;
1684
0
}
1685
1686
1687
_PyXI_excinfo *
1688
_PyXI_NewExcInfo(PyObject *exc)
1689
0
{
1690
0
    assert(!PyErr_Occurred());
1691
0
    if (exc == NULL || exc == Py_None) {
1692
0
        PyErr_SetString(PyExc_ValueError, "missing exc");
1693
0
        return NULL;
1694
0
    }
1695
0
    _PyXI_excinfo *info = PyMem_RawCalloc(1, sizeof(_PyXI_excinfo));
1696
0
    if (info == NULL) {
1697
0
        PyErr_NoMemory();
1698
0
        return NULL;
1699
0
    }
1700
0
    const char *failure;
1701
0
    if (PyExceptionInstance_Check(exc) || PyExceptionClass_Check(exc)) {
1702
0
        failure = _PyXI_excinfo_InitFromException(info, exc);
1703
0
    }
1704
0
    else {
1705
0
        failure = _PyXI_excinfo_InitFromObject(info, exc);
1706
0
    }
1707
0
    if (failure != NULL) {
1708
0
        PyMem_RawFree(info);
1709
0
        set_exc_with_cause(PyExc_Exception, failure);
1710
0
        return NULL;
1711
0
    }
1712
0
    return info;
1713
0
}
1714
1715
void
1716
_PyXI_FreeExcInfo(_PyXI_excinfo *info)
1717
0
{
1718
0
    assert(info != NULL);
1719
0
    _PyXI_excinfo_clear(info);
1720
0
    PyMem_RawFree(info);
1721
0
}
1722
1723
PyObject *
1724
_PyXI_FormatExcInfo(_PyXI_excinfo *info)
1725
0
{
1726
0
    return _PyXI_excinfo_format(info);
1727
0
}
1728
1729
PyObject *
1730
_PyXI_ExcInfoAsObject(_PyXI_excinfo *info)
1731
0
{
1732
0
    return _PyXI_excinfo_AsObject(info);
1733
0
}
1734
1735
1736
/***************************/
1737
/* short-term data sharing */
1738
/***************************/
1739
1740
/* error codes */
1741
1742
static int
1743
_PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
1744
0
{
1745
0
    PyThreadState *tstate = _PyThreadState_GET();
1746
1747
0
    assert(!PyErr_Occurred());
1748
0
    assert(code != _PyXI_ERR_NO_ERROR);
1749
0
    assert(code != _PyXI_ERR_UNCAUGHT_EXCEPTION);
1750
0
    switch (code) {
1751
0
    case _PyXI_ERR_OTHER:
1752
        // XXX msg?
1753
0
        PyErr_SetNone(PyExc_InterpreterError);
1754
0
        break;
1755
0
    case _PyXI_ERR_NO_MEMORY:
1756
0
        PyErr_NoMemory();
1757
0
        break;
1758
0
    case _PyXI_ERR_ALREADY_RUNNING:
1759
0
        assert(interp != NULL);
1760
0
        _PyErr_SetInterpreterAlreadyRunning();
1761
0
        break;
1762
0
    case _PyXI_ERR_MAIN_NS_FAILURE:
1763
0
        PyErr_SetString(PyExc_InterpreterError,
1764
0
                        "failed to get __main__ namespace");
1765
0
        break;
1766
0
    case _PyXI_ERR_APPLY_NS_FAILURE:
1767
0
        PyErr_SetString(PyExc_InterpreterError,
1768
0
                        "failed to apply namespace to __main__");
1769
0
        break;
1770
0
    case _PyXI_ERR_PRESERVE_FAILURE:
1771
0
        PyErr_SetString(PyExc_InterpreterError,
1772
0
                        "failed to preserve objects across session");
1773
0
        break;
1774
0
    case _PyXI_ERR_EXC_PROPAGATION_FAILURE:
1775
0
        PyErr_SetString(PyExc_InterpreterError,
1776
0
                        "failed to transfer exception between interpreters");
1777
0
        break;
1778
0
    case _PyXI_ERR_NOT_SHAREABLE:
1779
0
        _set_xid_lookup_failure(tstate, NULL, NULL, NULL);
1780
0
        break;
1781
0
    default:
1782
#ifdef Py_DEBUG
1783
        Py_FatalError("unsupported error code");
1784
#else
1785
0
        PyErr_Format(PyExc_RuntimeError, "unsupported error code %d", code);
1786
0
#endif
1787
0
    }
1788
0
    assert(PyErr_Occurred());
1789
0
    return -1;
1790
0
}
1791
1792
/* basic failure info */
1793
1794
struct xi_failure {
1795
    // The kind of error to propagate.
1796
    _PyXI_errcode code;
1797
    // The propagated message.
1798
    const char *msg;
1799
    int msg_owned;
1800
};  // _PyXI_failure
1801
1802
0
#define XI_FAILURE_INIT (_PyXI_failure){ .code = _PyXI_ERR_NO_ERROR }
1803
1804
static void
1805
clear_xi_failure(_PyXI_failure *failure)
1806
0
{
1807
0
    if (failure->msg != NULL && failure->msg_owned) {
1808
0
        PyMem_RawFree((void*)failure->msg);
1809
0
    }
1810
0
    *failure = XI_FAILURE_INIT;
1811
0
}
1812
1813
static void
1814
copy_xi_failure(_PyXI_failure *dest, _PyXI_failure *src)
1815
0
{
1816
0
    *dest = *src;
1817
0
    dest->msg_owned = 0;
1818
0
}
1819
1820
_PyXI_failure *
1821
_PyXI_NewFailure(void)
1822
0
{
1823
0
    _PyXI_failure *failure = PyMem_RawMalloc(sizeof(_PyXI_failure));
1824
0
    if (failure == NULL) {
1825
0
        PyErr_NoMemory();
1826
0
        return NULL;
1827
0
    }
1828
0
    *failure = XI_FAILURE_INIT;
1829
0
    return failure;
1830
0
}
1831
1832
void
1833
_PyXI_FreeFailure(_PyXI_failure *failure)
1834
0
{
1835
0
    clear_xi_failure(failure);
1836
0
    PyMem_RawFree(failure);
1837
0
}
1838
1839
_PyXI_errcode
1840
_PyXI_GetFailureCode(_PyXI_failure *failure)
1841
0
{
1842
0
    if (failure == NULL) {
1843
0
        return _PyXI_ERR_NO_ERROR;
1844
0
    }
1845
0
    return failure->code;
1846
0
}
1847
1848
void
1849
_PyXI_InitFailureUTF8(_PyXI_failure *failure,
1850
                      _PyXI_errcode code, const char *msg)
1851
0
{
1852
0
    *failure = (_PyXI_failure){
1853
0
        .code = code,
1854
0
        .msg = msg,
1855
0
        .msg_owned = 0,
1856
0
    };
1857
0
}
1858
1859
int
1860
_PyXI_InitFailure(_PyXI_failure *failure, _PyXI_errcode code, PyObject *obj)
1861
0
{
1862
0
    *failure = (_PyXI_failure){
1863
0
        .code = code,
1864
0
        .msg = NULL,
1865
0
        .msg_owned = 0,
1866
0
    };
1867
0
    if (obj == NULL) {
1868
0
        return 0;
1869
0
    }
1870
1871
0
    PyObject *msgobj = PyObject_Str(obj);
1872
0
    if (msgobj == NULL) {
1873
0
        return -1;
1874
0
    }
1875
    // This will leak if not paired with clear_xi_failure().
1876
    // That happens automatically in _capture_current_exception().
1877
0
    const char *msg = _copy_string_obj_raw(msgobj, NULL);
1878
0
    Py_DECREF(msgobj);
1879
0
    if (msg == NULL) {
1880
0
        return -1;
1881
0
    }
1882
0
    *failure = (_PyXI_failure){
1883
0
        .code = code,
1884
0
        .msg = msg,
1885
0
        .msg_owned = 1,
1886
0
    };
1887
0
    return 0;
1888
0
}
1889
1890
/* shared exceptions */
1891
1892
typedef struct {
1893
    // The originating interpreter.
1894
    PyInterpreterState *interp;
1895
    // The error to propagate, if different from the uncaught exception.
1896
    _PyXI_failure *override;
1897
    _PyXI_failure _override;
1898
    // The exception information to propagate, if applicable.
1899
    // This is populated only for some error codes,
1900
    // but always for _PyXI_ERR_UNCAUGHT_EXCEPTION.
1901
    _PyXI_excinfo uncaught;
1902
} _PyXI_error;
1903
1904
static void
1905
xi_error_clear(_PyXI_error *err)
1906
0
{
1907
0
    err->interp = NULL;
1908
0
    if (err->override != NULL) {
1909
0
        clear_xi_failure(err->override);
1910
0
    }
1911
0
    _PyXI_excinfo_clear(&err->uncaught);
1912
0
}
1913
1914
static int
1915
xi_error_is_set(_PyXI_error *error)
1916
0
{
1917
0
    if (error->override != NULL) {
1918
0
        assert(error->override->code != _PyXI_ERR_NO_ERROR);
1919
0
        assert(error->override->code != _PyXI_ERR_UNCAUGHT_EXCEPTION
1920
0
               || excinfo_is_set(&error->uncaught));
1921
0
        return 1;
1922
0
    }
1923
0
    return excinfo_is_set(&error->uncaught);
1924
0
}
1925
1926
static int
1927
xi_error_has_override(_PyXI_error *err)
1928
0
{
1929
0
    if (err->override == NULL) {
1930
0
        return 0;
1931
0
    }
1932
0
    return (err->override->code != _PyXI_ERR_NO_ERROR
1933
0
            && err->override->code != _PyXI_ERR_UNCAUGHT_EXCEPTION);
1934
0
}
1935
1936
static PyObject *
1937
xi_error_resolve_current_exc(PyThreadState *tstate,
1938
                             _PyXI_failure *override)
1939
0
{
1940
0
    assert(override == NULL || override->code != _PyXI_ERR_NO_ERROR);
1941
1942
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
1943
0
    if (exc == NULL) {
1944
0
        assert(override == NULL
1945
0
               || override->code != _PyXI_ERR_UNCAUGHT_EXCEPTION);
1946
0
    }
1947
0
    else if (override == NULL) {
1948
        // This is equivalent to _PyXI_ERR_UNCAUGHT_EXCEPTION.
1949
0
    }
1950
0
    else if (override->code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
1951
        // We want to actually capture the current exception.
1952
0
    }
1953
0
    else if (exc != NULL) {
1954
        // It might make sense to do similarly for other codes.
1955
0
        if (override->code == _PyXI_ERR_ALREADY_RUNNING) {
1956
            // We don't need the exception info.
1957
0
            Py_CLEAR(exc);
1958
0
        }
1959
        // ...else we want to actually capture the current exception.
1960
0
    }
1961
0
    return exc;
1962
0
}
1963
1964
static void
1965
xi_error_set_override(PyThreadState *tstate, _PyXI_error *err,
1966
                      _PyXI_failure *override)
1967
0
{
1968
0
    assert(err->override == NULL);
1969
0
    assert(override != NULL);
1970
0
    assert(override->code != _PyXI_ERR_NO_ERROR);
1971
    // Use xi_error_set_exc() instead of setting _PyXI_ERR_UNCAUGHT_EXCEPTION..
1972
0
    assert(override->code != _PyXI_ERR_UNCAUGHT_EXCEPTION);
1973
0
    err->override = &err->_override;
1974
    // The caller still owns override->msg.
1975
0
    copy_xi_failure(&err->_override, override);
1976
0
    err->interp = tstate->interp;
1977
0
}
1978
1979
static void
1980
xi_error_set_override_code(PyThreadState *tstate, _PyXI_error *err,
1981
                           _PyXI_errcode code)
1982
0
{
1983
0
    _PyXI_failure override = XI_FAILURE_INIT;
1984
0
    override.code = code;
1985
0
    xi_error_set_override(tstate, err, &override);
1986
0
}
1987
1988
static const char *
1989
xi_error_set_exc(PyThreadState *tstate, _PyXI_error *err, PyObject *exc)
1990
0
{
1991
0
    assert(!_PyErr_Occurred(tstate));
1992
0
    assert(!xi_error_is_set(err));
1993
0
    assert(err->override == NULL);
1994
0
    assert(err->interp == NULL);
1995
0
    assert(exc != NULL);
1996
0
    const char *failure =
1997
0
                _PyXI_excinfo_InitFromException(&err->uncaught, exc);
1998
0
    if (failure != NULL) {
1999
        // We failed to initialize err->uncaught.
2000
        // XXX Print the excobj/traceback?  Emit a warning?
2001
        // XXX Print the current exception/traceback?
2002
0
        if (_PyErr_ExceptionMatches(tstate, PyExc_MemoryError)) {
2003
0
            xi_error_set_override_code(tstate, err, _PyXI_ERR_NO_MEMORY);
2004
0
        }
2005
0
        else {
2006
0
            xi_error_set_override_code(tstate, err, _PyXI_ERR_OTHER);
2007
0
        }
2008
0
        PyErr_Clear();
2009
0
    }
2010
0
    return failure;
2011
0
}
2012
2013
static PyObject *
2014
_PyXI_ApplyError(_PyXI_error *error, const char *failure)
2015
0
{
2016
0
    PyThreadState *tstate = PyThreadState_Get();
2017
2018
0
    if (failure != NULL) {
2019
0
        xi_error_clear(error);
2020
0
        return NULL;
2021
0
    }
2022
2023
0
    _PyXI_errcode code = _PyXI_ERR_UNCAUGHT_EXCEPTION;
2024
0
    if (error->override != NULL) {
2025
0
        code = error->override->code;
2026
0
        assert(code != _PyXI_ERR_NO_ERROR);
2027
0
    }
2028
2029
0
    if (code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
2030
        // We will raise an exception that proxies the propagated exception.
2031
0
       return _PyXI_excinfo_AsObject(&error->uncaught);
2032
0
    }
2033
0
    else if (code == _PyXI_ERR_NOT_SHAREABLE) {
2034
        // Propagate the exception directly.
2035
0
        assert(!_PyErr_Occurred(tstate));
2036
0
        PyObject *cause = NULL;
2037
0
        if (excinfo_is_set(&error->uncaught)) {
2038
            // Maybe instead set a PyExc_ExceptionSnapshot as __cause__?
2039
            // That type doesn't exist currently
2040
            // but would look like interpreters.ExecutionFailed.
2041
0
            _PyXI_excinfo_Apply(&error->uncaught, PyExc_Exception);
2042
0
            cause = _PyErr_GetRaisedException(tstate);
2043
0
        }
2044
0
        const char *msg = error->override != NULL
2045
0
            ? error->override->msg
2046
0
            : error->uncaught.msg;
2047
0
        _set_xid_lookup_failure(tstate, NULL, msg, cause);
2048
0
        Py_XDECREF(cause);
2049
0
    }
2050
0
    else {
2051
        // Raise an exception corresponding to the code.
2052
0
        (void)_PyXI_ApplyErrorCode(code, error->interp);
2053
0
        assert(error->override == NULL || error->override->msg == NULL);
2054
0
        if (excinfo_is_set(&error->uncaught)) {
2055
            // __context__ will be set to a proxy of the propagated exception.
2056
            // (or use PyExc_ExceptionSnapshot like _PyXI_ERR_NOT_SHAREABLE?)
2057
0
            PyObject *exc = _PyErr_GetRaisedException(tstate);
2058
0
            _PyXI_excinfo_Apply(&error->uncaught, PyExc_InterpreterError);
2059
0
            PyObject *exc2 = _PyErr_GetRaisedException(tstate);
2060
0
            PyException_SetContext(exc, exc2);
2061
0
            _PyErr_SetRaisedException(tstate, exc);
2062
0
        }
2063
0
    }
2064
0
    assert(PyErr_Occurred());
2065
0
    return NULL;
2066
0
}
2067
2068
/* shared namespaces */
2069
2070
/* Shared namespaces are expected to have relatively short lifetimes.
2071
   This means dealloc of a shared namespace will normally happen "soon".
2072
   Namespace items hold cross-interpreter data, which must get released.
2073
   If the namespace/items are cleared in a different interpreter than
2074
   where the items' cross-interpreter data was set then that will cause
2075
   pending calls to be used to release the cross-interpreter data.
2076
   The tricky bit is that the pending calls can happen sufficiently
2077
   later that the namespace/items might already be deallocated.  This is
2078
   a problem if the cross-interpreter data is allocated as part of a
2079
   namespace item.  If that's the case then we must ensure the shared
2080
   namespace is only cleared/freed *after* that data has been released. */
2081
2082
typedef struct _sharednsitem {
2083
    const char *name;
2084
    _PyXIData_t *xidata;
2085
    // We could have a "PyXIData _data" field, so it would
2086
    // be allocated as part of the item and avoid an extra allocation.
2087
    // However, doing so adds a bunch of complexity because we must
2088
    // ensure the item isn't freed before a pending call might happen
2089
    // in a different interpreter to release the XI data.
2090
} _PyXI_namespace_item;
2091
2092
#ifndef NDEBUG
2093
static int
2094
_sharednsitem_is_initialized(_PyXI_namespace_item *item)
2095
{
2096
    if (item->name != NULL) {
2097
        return 1;
2098
    }
2099
    return 0;
2100
}
2101
#endif
2102
2103
static int
2104
_sharednsitem_init(_PyXI_namespace_item *item, PyObject *key)
2105
0
{
2106
0
    item->name = _copy_string_obj_raw(key, NULL);
2107
0
    if (item->name == NULL) {
2108
0
        assert(!_sharednsitem_is_initialized(item));
2109
0
        return -1;
2110
0
    }
2111
0
    item->xidata = NULL;
2112
0
    assert(_sharednsitem_is_initialized(item));
2113
0
    return 0;
2114
0
}
2115
2116
static int
2117
_sharednsitem_has_value(_PyXI_namespace_item *item, int64_t *p_interpid)
2118
0
{
2119
0
    if (item->xidata == NULL) {
2120
0
        return 0;
2121
0
    }
2122
0
    if (p_interpid != NULL) {
2123
0
        *p_interpid = _PyXIData_INTERPID(item->xidata);
2124
0
    }
2125
0
    return 1;
2126
0
}
2127
2128
static int
2129
_sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value,
2130
                        xidata_fallback_t fallback)
2131
0
{
2132
0
    assert(_sharednsitem_is_initialized(item));
2133
0
    assert(item->xidata == NULL);
2134
0
    item->xidata = _PyXIData_New();
2135
0
    if (item->xidata == NULL) {
2136
0
        return -1;
2137
0
    }
2138
0
    PyThreadState *tstate = PyThreadState_Get();
2139
0
    if (_PyObject_GetXIData(tstate, value, fallback, item->xidata) < 0) {
2140
0
        PyMem_RawFree(item->xidata);
2141
0
        item->xidata = NULL;
2142
        // The caller may want to propagate PyExc_NotShareableError
2143
        // if currently switched between interpreters.
2144
0
        return -1;
2145
0
    }
2146
0
    return 0;
2147
0
}
2148
2149
static void
2150
_sharednsitem_clear_value(_PyXI_namespace_item *item)
2151
0
{
2152
0
    _PyXIData_t *xidata = item->xidata;
2153
0
    if (xidata != NULL) {
2154
0
        item->xidata = NULL;
2155
0
        int rawfree = 1;
2156
0
        (void)_release_xid_data(xidata, rawfree);
2157
0
    }
2158
0
}
2159
2160
static void
2161
_sharednsitem_clear(_PyXI_namespace_item *item)
2162
0
{
2163
0
    if (item->name != NULL) {
2164
0
        PyMem_RawFree((void *)item->name);
2165
0
        item->name = NULL;
2166
0
    }
2167
0
    _sharednsitem_clear_value(item);
2168
0
}
2169
2170
static int
2171
_sharednsitem_copy_from_ns(struct _sharednsitem *item, PyObject *ns,
2172
                           xidata_fallback_t fallback)
2173
0
{
2174
0
    assert(item->name != NULL);
2175
0
    assert(item->xidata == NULL);
2176
0
    PyObject *value = PyDict_GetItemString(ns, item->name);  // borrowed
2177
0
    if (value == NULL) {
2178
0
        if (PyErr_Occurred()) {
2179
0
            return -1;
2180
0
        }
2181
        // When applied, this item will be set to the default (or fail).
2182
0
        return 0;
2183
0
    }
2184
0
    if (_sharednsitem_set_value(item, value, fallback) < 0) {
2185
0
        return -1;
2186
0
    }
2187
0
    return 0;
2188
0
}
2189
2190
static int
2191
_sharednsitem_apply(_PyXI_namespace_item *item, PyObject *ns, PyObject *dflt)
2192
0
{
2193
0
    PyObject *name = PyUnicode_FromString(item->name);
2194
0
    if (name == NULL) {
2195
0
        return -1;
2196
0
    }
2197
0
    PyObject *value;
2198
0
    if (item->xidata != NULL) {
2199
0
        value = _PyXIData_NewObject(item->xidata);
2200
0
        if (value == NULL) {
2201
0
            Py_DECREF(name);
2202
0
            return -1;
2203
0
        }
2204
0
    }
2205
0
    else {
2206
0
        value = Py_NewRef(dflt);
2207
0
    }
2208
0
    int res = PyDict_SetItem(ns, name, value);
2209
0
    Py_DECREF(name);
2210
0
    Py_DECREF(value);
2211
0
    return res;
2212
0
}
2213
2214
2215
typedef struct {
2216
    Py_ssize_t maxitems;
2217
    Py_ssize_t numnames;
2218
    Py_ssize_t numvalues;
2219
    _PyXI_namespace_item items[1];
2220
} _PyXI_namespace;
2221
2222
#ifndef NDEBUG
2223
static int
2224
_sharedns_check_counts(_PyXI_namespace *ns)
2225
{
2226
    if (ns->maxitems <= 0) {
2227
        return 0;
2228
    }
2229
    if (ns->numnames < 0) {
2230
        return 0;
2231
    }
2232
    if (ns->numnames > ns->maxitems) {
2233
        return 0;
2234
    }
2235
    if (ns->numvalues < 0) {
2236
        return 0;
2237
    }
2238
    if (ns->numvalues > ns->numnames) {
2239
        return 0;
2240
    }
2241
    return 1;
2242
}
2243
2244
static int
2245
_sharedns_check_consistency(_PyXI_namespace *ns)
2246
{
2247
    if (!_sharedns_check_counts(ns)) {
2248
        return 0;
2249
    }
2250
2251
    Py_ssize_t i = 0;
2252
    _PyXI_namespace_item *item;
2253
    if (ns->numvalues > 0) {
2254
        item = &ns->items[0];
2255
        if (!_sharednsitem_is_initialized(item)) {
2256
            return 0;
2257
        }
2258
        int64_t interpid0 = -1;
2259
        if (!_sharednsitem_has_value(item, &interpid0)) {
2260
            return 0;
2261
        }
2262
        i += 1;
2263
        for (; i < ns->numvalues; i++) {
2264
            item = &ns->items[i];
2265
            if (!_sharednsitem_is_initialized(item)) {
2266
                return 0;
2267
            }
2268
            int64_t interpid = -1;
2269
            if (!_sharednsitem_has_value(item, &interpid)) {
2270
                return 0;
2271
            }
2272
            if (interpid != interpid0) {
2273
                return 0;
2274
            }
2275
        }
2276
    }
2277
    for (; i < ns->numnames; i++) {
2278
        item = &ns->items[i];
2279
        if (!_sharednsitem_is_initialized(item)) {
2280
            return 0;
2281
        }
2282
        if (_sharednsitem_has_value(item, NULL)) {
2283
            return 0;
2284
        }
2285
    }
2286
    for (; i < ns->maxitems; i++) {
2287
        item = &ns->items[i];
2288
        if (_sharednsitem_is_initialized(item)) {
2289
            return 0;
2290
        }
2291
        if (_sharednsitem_has_value(item, NULL)) {
2292
            return 0;
2293
        }
2294
    }
2295
    return 1;
2296
}
2297
#endif
2298
2299
static _PyXI_namespace *
2300
_sharedns_alloc(Py_ssize_t maxitems)
2301
0
{
2302
0
    if (maxitems < 0) {
2303
0
        if (!PyErr_Occurred()) {
2304
0
            PyErr_BadInternalCall();
2305
0
        }
2306
0
        return NULL;
2307
0
    }
2308
0
    else if (maxitems == 0) {
2309
0
        PyErr_SetString(PyExc_ValueError, "empty namespaces not allowed");
2310
0
        return NULL;
2311
0
    }
2312
2313
    // Check for overflow.
2314
0
    size_t fixedsize = sizeof(_PyXI_namespace) - sizeof(_PyXI_namespace_item);
2315
0
    if ((size_t)maxitems >
2316
0
        ((size_t)PY_SSIZE_T_MAX - fixedsize) / sizeof(_PyXI_namespace_item))
2317
0
    {
2318
0
        PyErr_NoMemory();
2319
0
        return NULL;
2320
0
    }
2321
2322
    // Allocate the value, including items.
2323
0
    size_t size = fixedsize + sizeof(_PyXI_namespace_item) * maxitems;
2324
2325
0
    _PyXI_namespace *ns = PyMem_RawCalloc(size, 1);
2326
0
    if (ns == NULL) {
2327
0
        PyErr_NoMemory();
2328
0
        return NULL;
2329
0
    }
2330
0
    ns->maxitems = maxitems;
2331
0
    assert(_sharedns_check_consistency(ns));
2332
0
    return ns;
2333
0
}
2334
2335
static void
2336
_sharedns_free(_PyXI_namespace *ns)
2337
0
{
2338
    // If we weren't always dynamically allocating the cross-interpreter
2339
    // data in each item then we would need to use a pending call
2340
    // to call _sharedns_free(), to avoid the race between freeing
2341
    // the shared namespace and releasing the XI data.
2342
0
    assert(_sharedns_check_counts(ns));
2343
0
    Py_ssize_t i = 0;
2344
0
    _PyXI_namespace_item *item;
2345
0
    if (ns->numvalues > 0) {
2346
        // One or more items may have interpreter-specific data.
2347
#ifndef NDEBUG
2348
        int64_t interpid = PyInterpreterState_GetID(PyInterpreterState_Get());
2349
        int64_t interpid_i;
2350
#endif
2351
0
        for (; i < ns->numvalues; i++) {
2352
0
            item = &ns->items[i];
2353
0
            assert(_sharednsitem_is_initialized(item));
2354
            // While we do want to ensure consistency across items,
2355
            // technically they don't need to match the current
2356
            // interpreter.  However, we keep the constraint for
2357
            // simplicity, by giving _PyXI_FreeNamespace() the exclusive
2358
            // responsibility of dealing with the owning interpreter.
2359
0
            assert(_sharednsitem_has_value(item, &interpid_i));
2360
0
            assert(interpid_i == interpid);
2361
0
            _sharednsitem_clear(item);
2362
0
        }
2363
0
    }
2364
0
    for (; i < ns->numnames; i++) {
2365
0
        item = &ns->items[i];
2366
0
        assert(_sharednsitem_is_initialized(item));
2367
0
        assert(!_sharednsitem_has_value(item, NULL));
2368
0
        _sharednsitem_clear(item);
2369
0
    }
2370
#ifndef NDEBUG
2371
    for (; i < ns->maxitems; i++) {
2372
        item = &ns->items[i];
2373
        assert(!_sharednsitem_is_initialized(item));
2374
        assert(!_sharednsitem_has_value(item, NULL));
2375
    }
2376
#endif
2377
2378
0
    PyMem_RawFree(ns);
2379
0
}
2380
2381
static _PyXI_namespace *
2382
_create_sharedns(PyObject *names)
2383
0
{
2384
0
    assert(names != NULL);
2385
0
    Py_ssize_t numnames = PyDict_CheckExact(names)
2386
0
        ? PyDict_Size(names)
2387
0
        : PySequence_Size(names);
2388
2389
0
    _PyXI_namespace *ns = _sharedns_alloc(numnames);
2390
0
    if (ns == NULL) {
2391
0
        return NULL;
2392
0
    }
2393
0
    _PyXI_namespace_item *items = ns->items;
2394
2395
    // Fill in the names.
2396
0
    if (PyDict_CheckExact(names)) {
2397
0
        Py_ssize_t i = 0;
2398
0
        Py_ssize_t pos = 0;
2399
0
        PyObject *name;
2400
0
        while(PyDict_Next(names, &pos, &name, NULL)) {
2401
0
            if (_sharednsitem_init(&items[i], name) < 0) {
2402
0
                goto error;
2403
0
            }
2404
0
            ns->numnames += 1;
2405
0
            i += 1;
2406
0
        }
2407
0
    }
2408
0
    else if (PySequence_Check(names)) {
2409
0
        for (Py_ssize_t i = 0; i < numnames; i++) {
2410
0
            PyObject *name = PySequence_GetItem(names, i);
2411
0
            if (name == NULL) {
2412
0
                goto error;
2413
0
            }
2414
0
            int res = _sharednsitem_init(&items[i], name);
2415
0
            Py_DECREF(name);
2416
0
            if (res < 0) {
2417
0
                goto error;
2418
0
            }
2419
0
            ns->numnames += 1;
2420
0
        }
2421
0
    }
2422
0
    else {
2423
0
        PyErr_SetString(PyExc_NotImplementedError,
2424
0
                        "non-sequence namespace not supported");
2425
0
        goto error;
2426
0
    }
2427
0
    assert(ns->numnames == ns->maxitems);
2428
0
    return ns;
2429
2430
0
error:
2431
0
    _sharedns_free(ns);
2432
0
    return NULL;
2433
0
}
2434
2435
static void _propagate_not_shareable_error(PyThreadState *,
2436
                                           _PyXI_failure *);
2437
2438
static int
2439
_fill_sharedns(_PyXI_namespace *ns, PyObject *nsobj,
2440
               xidata_fallback_t fallback, _PyXI_failure *p_err)
2441
0
{
2442
    // All items are expected to be shareable.
2443
0
    assert(_sharedns_check_counts(ns));
2444
0
    assert(ns->numnames == ns->maxitems);
2445
0
    assert(ns->numvalues == 0);
2446
0
    PyThreadState *tstate = PyThreadState_Get();
2447
0
    for (Py_ssize_t i=0; i < ns->maxitems; i++) {
2448
0
        if (_sharednsitem_copy_from_ns(&ns->items[i], nsobj, fallback) < 0) {
2449
0
            if (p_err != NULL) {
2450
0
                _propagate_not_shareable_error(tstate, p_err);
2451
0
            }
2452
            // Clear out the ones we set so far.
2453
0
            for (Py_ssize_t j=0; j < i; j++) {
2454
0
                _sharednsitem_clear_value(&ns->items[j]);
2455
0
                ns->numvalues -= 1;
2456
0
            }
2457
0
            return -1;
2458
0
        }
2459
0
        ns->numvalues += 1;
2460
0
    }
2461
0
    return 0;
2462
0
}
2463
2464
static int
2465
_sharedns_free_pending(void *data)
2466
0
{
2467
0
    _sharedns_free((_PyXI_namespace *)data);
2468
0
    return 0;
2469
0
}
2470
2471
static void
2472
_destroy_sharedns(_PyXI_namespace *ns)
2473
0
{
2474
0
    assert(_sharedns_check_counts(ns));
2475
0
    assert(ns->numnames == ns->maxitems);
2476
0
    if (ns->numvalues == 0) {
2477
0
        _sharedns_free(ns);
2478
0
        return;
2479
0
    }
2480
2481
0
    int64_t interpid0;
2482
0
    if (!_sharednsitem_has_value(&ns->items[0], &interpid0)) {
2483
        // This shouldn't have been possible.
2484
        // We can deal with it in _sharedns_free().
2485
0
        _sharedns_free(ns);
2486
0
        return;
2487
0
    }
2488
0
    PyInterpreterState *interp = _PyInterpreterState_LookUpID(interpid0);
2489
0
    if (interp == PyInterpreterState_Get()) {
2490
0
        _sharedns_free(ns);
2491
0
        return;
2492
0
    }
2493
2494
    // One or more items may have interpreter-specific data.
2495
    // Currently the xidata for each value is dynamically allocated,
2496
    // so technically we don't need to worry about that.
2497
    // However, explicitly adding a pending call here is simpler.
2498
0
    (void)_Py_CallInInterpreter(interp, _sharedns_free_pending, ns);
2499
0
}
2500
2501
static int
2502
_apply_sharedns(_PyXI_namespace *ns, PyObject *nsobj, PyObject *dflt)
2503
0
{
2504
0
    for (Py_ssize_t i=0; i < ns->maxitems; i++) {
2505
0
        if (_sharednsitem_apply(&ns->items[i], nsobj, dflt) != 0) {
2506
0
            return -1;
2507
0
        }
2508
0
    }
2509
0
    return 0;
2510
0
}
2511
2512
2513
/*********************************/
2514
/* switched-interpreter sessions */
2515
/*********************************/
2516
2517
struct xi_session {
2518
#define SESSION_UNUSED 0
2519
0
#define SESSION_ACTIVE 1
2520
    int status;
2521
    int switched;
2522
2523
    // Once a session has been entered, this is the tstate that was
2524
    // current before the session.  If it is different from cur_tstate
2525
    // then we must have switched interpreters.  Either way, this will
2526
    // be the current tstate once we exit the session.
2527
    PyThreadState *prev_tstate;
2528
    // Once a session has been entered, this is the current tstate.
2529
    // It must be current when the session exits.
2530
    PyThreadState *init_tstate;
2531
    // This is true if init_tstate needs cleanup during exit.
2532
    int own_init_tstate;
2533
2534
    // This is true if, while entering the session, init_thread took
2535
    // "ownership" of the interpreter's __main__ module.  This means
2536
    // it is the only thread that is allowed to run code there.
2537
    // (Caveat: for now, users may still run exec() against the
2538
    // __main__ module's dict, though that isn't advisable.)
2539
    int running;
2540
    // This is a cached reference to the __dict__ of the entered
2541
    // interpreter's __main__ module.  It is looked up when at the
2542
    // beginning of the session as a convenience.
2543
    PyObject *main_ns;
2544
2545
    // This is a dict of objects that will be available (via sharing)
2546
    // once the session exits.  Do not access this directly; use
2547
    // _PyXI_Preserve() and _PyXI_GetPreserved() instead;
2548
    PyObject *_preserved;
2549
};
2550
2551
_PyXI_session *
2552
_PyXI_NewSession(void)
2553
0
{
2554
0
    _PyXI_session *session = PyMem_RawCalloc(1, sizeof(_PyXI_session));
2555
0
    if (session == NULL) {
2556
0
        PyErr_NoMemory();
2557
0
        return NULL;
2558
0
    }
2559
0
    return session;
2560
0
}
2561
2562
void
2563
_PyXI_FreeSession(_PyXI_session *session)
2564
0
{
2565
0
    assert(session->status == SESSION_UNUSED);
2566
0
    PyMem_RawFree(session);
2567
0
}
2568
2569
2570
static inline int
2571
_session_is_active(_PyXI_session *session)
2572
0
{
2573
0
    return session->status == SESSION_ACTIVE;
2574
0
}
2575
2576
2577
/* enter/exit a cross-interpreter session */
2578
2579
static void
2580
_enter_session(_PyXI_session *session, PyInterpreterState *interp)
2581
0
{
2582
    // Set here and cleared in _exit_session().
2583
0
    assert(session->status == SESSION_UNUSED);
2584
0
    assert(!session->own_init_tstate);
2585
0
    assert(session->init_tstate == NULL);
2586
0
    assert(session->prev_tstate == NULL);
2587
    // Set elsewhere and cleared in _exit_session().
2588
0
    assert(!session->running);
2589
0
    assert(session->main_ns == NULL);
2590
2591
    // Switch to interpreter.
2592
0
    PyThreadState *tstate = PyThreadState_Get();
2593
0
    PyThreadState *prev = tstate;
2594
0
    int same_interp = (interp == tstate->interp);
2595
0
    if (!same_interp) {
2596
0
        tstate = _PyThreadState_NewBound(interp, _PyThreadState_WHENCE_EXEC);
2597
        // XXX Possible GILState issues?
2598
0
        PyThreadState *swapped = PyThreadState_Swap(tstate);
2599
0
        assert(swapped == prev);
2600
0
        (void)swapped;
2601
0
    }
2602
2603
0
    *session = (_PyXI_session){
2604
0
        .status = SESSION_ACTIVE,
2605
0
        .switched = !same_interp,
2606
0
        .init_tstate = tstate,
2607
0
        .prev_tstate = prev,
2608
0
        .own_init_tstate = !same_interp,
2609
0
    };
2610
0
}
2611
2612
static void
2613
_exit_session(_PyXI_session *session)
2614
0
{
2615
0
    PyThreadState *tstate = session->init_tstate;
2616
0
    assert(tstate != NULL);
2617
0
    assert(PyThreadState_Get() == tstate);
2618
0
    assert(!_PyErr_Occurred(tstate));
2619
2620
    // Release any of the entered interpreters resources.
2621
0
    Py_CLEAR(session->main_ns);
2622
0
    Py_CLEAR(session->_preserved);
2623
2624
    // Ensure this thread no longer owns __main__.
2625
0
    if (session->running) {
2626
0
        _PyInterpreterState_SetNotRunningMain(tstate->interp);
2627
0
        assert(!_PyErr_Occurred(tstate));
2628
0
        session->running = 0;
2629
0
    }
2630
2631
    // Switch back.
2632
0
    assert(session->prev_tstate != NULL);
2633
0
    if (session->prev_tstate != session->init_tstate) {
2634
0
        assert(session->own_init_tstate);
2635
0
        session->own_init_tstate = 0;
2636
0
        PyThreadState_Clear(tstate);
2637
0
        PyThreadState_Swap(session->prev_tstate);
2638
0
        PyThreadState_Delete(tstate);
2639
0
    }
2640
0
    else {
2641
0
        assert(!session->own_init_tstate);
2642
0
    }
2643
2644
0
    *session = (_PyXI_session){0};
2645
0
}
2646
2647
static void
2648
_propagate_not_shareable_error(PyThreadState *tstate,
2649
                               _PyXI_failure *override)
2650
0
{
2651
0
    assert(override != NULL);
2652
0
    PyObject *exctype = get_notshareableerror_type(tstate);
2653
0
    if (exctype == NULL) {
2654
0
        PyErr_FormatUnraisable(
2655
0
                "Exception ignored while propagating not shareable error");
2656
0
        return;
2657
0
    }
2658
0
    if (PyErr_ExceptionMatches(exctype)) {
2659
        // We want to propagate the exception directly.
2660
0
        *override = (_PyXI_failure){
2661
0
            .code = _PyXI_ERR_NOT_SHAREABLE,
2662
0
        };
2663
0
    }
2664
0
}
2665
2666
2667
static int _ensure_main_ns(_PyXI_session *, _PyXI_failure *);
2668
static const char * capture_session_error(_PyXI_session *, _PyXI_error *,
2669
                                          _PyXI_failure *);
2670
2671
int
2672
_PyXI_Enter(_PyXI_session *session,
2673
            PyInterpreterState *interp, PyObject *nsupdates,
2674
            _PyXI_session_result *result)
2675
0
{
2676
#ifndef NDEBUG
2677
    PyThreadState *tstate = _PyThreadState_GET();  // Only used for asserts
2678
#endif
2679
2680
    // Convert the attrs for cross-interpreter use.
2681
0
    _PyXI_namespace *sharedns = NULL;
2682
0
    if (nsupdates != NULL) {
2683
0
        assert(PyDict_Check(nsupdates));
2684
0
        Py_ssize_t len = PyDict_Size(nsupdates);
2685
0
        if (len < 0) {
2686
0
            if (result != NULL) {
2687
0
                result->errcode = _PyXI_ERR_APPLY_NS_FAILURE;
2688
0
            }
2689
0
            return -1;
2690
0
        }
2691
0
        if (len > 0) {
2692
0
            sharedns = _create_sharedns(nsupdates);
2693
0
            if (sharedns == NULL) {
2694
0
                if (result != NULL) {
2695
0
                    result->errcode = _PyXI_ERR_APPLY_NS_FAILURE;
2696
0
                }
2697
0
                return -1;
2698
0
            }
2699
            // For now we limit it to shareable objects.
2700
0
            xidata_fallback_t fallback = _PyXIDATA_XIDATA_ONLY;
2701
0
            _PyXI_failure _err = XI_FAILURE_INIT;
2702
0
            if (_fill_sharedns(sharedns, nsupdates, fallback, &_err) < 0) {
2703
0
                assert(_PyErr_Occurred(tstate));
2704
0
                if (_err.code == _PyXI_ERR_NO_ERROR) {
2705
0
                    _err.code = _PyXI_ERR_UNCAUGHT_EXCEPTION;
2706
0
                }
2707
0
                _destroy_sharedns(sharedns);
2708
0
                if (result != NULL) {
2709
0
                    assert(_err.msg == NULL);
2710
0
                    result->errcode = _err.code;
2711
0
                }
2712
0
                return -1;
2713
0
            }
2714
0
        }
2715
0
    }
2716
2717
    // Switch to the requested interpreter (if necessary).
2718
0
    _enter_session(session, interp);
2719
0
    _PyXI_failure override = XI_FAILURE_INIT;
2720
0
    override.code = _PyXI_ERR_UNCAUGHT_EXCEPTION;
2721
#ifndef NDEBUG
2722
    tstate = _PyThreadState_GET();
2723
#endif
2724
2725
    // Ensure this thread owns __main__.
2726
0
    if (_PyInterpreterState_SetRunningMain(interp) < 0) {
2727
        // In the case where we didn't switch interpreters, it would
2728
        // be more efficient to leave the exception in place and return
2729
        // immediately.  However, life is simpler if we don't.
2730
0
        override.code = _PyXI_ERR_ALREADY_RUNNING;
2731
0
        goto error;
2732
0
    }
2733
0
    session->running = 1;
2734
2735
    // Apply the cross-interpreter data.
2736
0
    if (sharedns != NULL) {
2737
0
        if (_ensure_main_ns(session, &override) < 0) {
2738
0
            goto error;
2739
0
        }
2740
0
        if (_apply_sharedns(sharedns, session->main_ns, NULL) < 0) {
2741
0
            override.code = _PyXI_ERR_APPLY_NS_FAILURE;
2742
0
            goto error;
2743
0
        }
2744
0
        _destroy_sharedns(sharedns);
2745
0
    }
2746
2747
0
    override.code = _PyXI_ERR_NO_ERROR;
2748
0
    assert(!_PyErr_Occurred(tstate));
2749
0
    return 0;
2750
2751
0
error:
2752
    // We want to propagate all exceptions here directly (best effort).
2753
0
    assert(override.code != _PyXI_ERR_NO_ERROR);
2754
0
    _PyXI_error err = {0};
2755
0
    const char *failure = capture_session_error(session, &err, &override);
2756
2757
    // Exit the session.
2758
0
    _exit_session(session);
2759
#ifndef NDEBUG
2760
    tstate = _PyThreadState_GET();
2761
#endif
2762
2763
0
    if (sharedns != NULL) {
2764
0
        _destroy_sharedns(sharedns);
2765
0
    }
2766
2767
    // Apply the error from the other interpreter.
2768
0
    PyObject *excinfo = _PyXI_ApplyError(&err, failure);
2769
0
    xi_error_clear(&err);
2770
0
    if (excinfo != NULL) {
2771
0
        if (result != NULL) {
2772
0
            result->excinfo = excinfo;
2773
0
        }
2774
0
        else {
2775
#ifdef Py_DEBUG
2776
            fprintf(stderr, "_PyXI_Enter(): uncaught exception discarded");
2777
#endif
2778
0
            Py_DECREF(excinfo);
2779
0
        }
2780
0
    }
2781
0
    assert(_PyErr_Occurred(tstate));
2782
2783
0
    return -1;
2784
0
}
2785
2786
static int _pop_preserved(_PyXI_session *, _PyXI_namespace **, PyObject **,
2787
                          _PyXI_failure *);
2788
static int _finish_preserved(_PyXI_namespace *, PyObject **);
2789
2790
int
2791
_PyXI_Exit(_PyXI_session *session, _PyXI_failure *override,
2792
           _PyXI_session_result *result)
2793
0
{
2794
0
    PyThreadState *tstate = _PyThreadState_GET();
2795
0
    int res = 0;
2796
2797
    // Capture the raised exception, if any.
2798
0
    _PyXI_error err = {0};
2799
0
    const char *failure = NULL;
2800
0
    if (override != NULL && override->code == _PyXI_ERR_NO_ERROR) {
2801
0
        assert(override->msg == NULL);
2802
0
        override = NULL;
2803
0
    }
2804
0
    if (_PyErr_Occurred(tstate)) {
2805
0
        failure = capture_session_error(session, &err, override);
2806
0
    }
2807
0
    else {
2808
0
        assert(override == NULL);
2809
0
    }
2810
2811
    // Capture the preserved namespace.
2812
0
    _PyXI_namespace *preserved = NULL;
2813
0
    PyObject *preservedobj = NULL;
2814
0
    if (result != NULL) {
2815
0
        assert(!_PyErr_Occurred(tstate));
2816
0
        _PyXI_failure _override = XI_FAILURE_INIT;
2817
0
        if (_pop_preserved(
2818
0
                    session, &preserved, &preservedobj, &_override) < 0)
2819
0
        {
2820
0
            assert(preserved == NULL);
2821
0
            assert(preservedobj == NULL);
2822
0
            if (xi_error_is_set(&err)) {
2823
                // XXX Chain the exception (i.e. set __context__)?
2824
0
                PyErr_FormatUnraisable(
2825
0
                    "Exception ignored while capturing preserved objects");
2826
0
                clear_xi_failure(&_override);
2827
0
            }
2828
0
            else {
2829
0
                if (_override.code == _PyXI_ERR_NO_ERROR) {
2830
0
                    _override.code = _PyXI_ERR_UNCAUGHT_EXCEPTION;
2831
0
                }
2832
0
                failure = capture_session_error(session, &err, &_override);
2833
0
            }
2834
0
        }
2835
0
    }
2836
2837
    // Exit the session.
2838
0
    assert(!_PyErr_Occurred(tstate));
2839
0
    _exit_session(session);
2840
0
    tstate = _PyThreadState_GET();
2841
2842
    // Restore the preserved namespace.
2843
0
    assert(preserved == NULL || preservedobj == NULL);
2844
0
    if (_finish_preserved(preserved, &preservedobj) < 0) {
2845
0
        assert(preservedobj == NULL);
2846
0
        if (xi_error_is_set(&err)) {
2847
            // XXX Chain the exception (i.e. set __context__)?
2848
0
            PyErr_FormatUnraisable(
2849
0
                "Exception ignored while capturing preserved objects");
2850
0
        }
2851
0
        else {
2852
0
            xi_error_set_override_code(
2853
0
                            tstate, &err, _PyXI_ERR_PRESERVE_FAILURE);
2854
0
            _propagate_not_shareable_error(tstate, err.override);
2855
0
        }
2856
0
    }
2857
0
    if (result != NULL) {
2858
0
        result->preserved = preservedobj;
2859
0
        result->errcode = err.override != NULL
2860
0
            ? err.override->code
2861
0
            : _PyXI_ERR_NO_ERROR;
2862
0
    }
2863
2864
    // Apply the error from the other interpreter, if any.
2865
0
    if (xi_error_is_set(&err)) {
2866
0
        res = -1;
2867
0
        assert(!_PyErr_Occurred(tstate));
2868
0
        PyObject *excinfo = _PyXI_ApplyError(&err, failure);
2869
0
        if (excinfo == NULL) {
2870
0
            assert(_PyErr_Occurred(tstate));
2871
0
            if (result != NULL && !xi_error_has_override(&err)) {
2872
0
                _PyXI_ClearResult(result);
2873
0
                *result = (_PyXI_session_result){
2874
0
                    .errcode = _PyXI_ERR_EXC_PROPAGATION_FAILURE,
2875
0
                };
2876
0
            }
2877
0
        }
2878
0
        else if (result != NULL) {
2879
0
            result->excinfo = excinfo;
2880
0
        }
2881
0
        else {
2882
#ifdef Py_DEBUG
2883
            fprintf(stderr, "_PyXI_Exit(): uncaught exception discarded");
2884
#endif
2885
0
            Py_DECREF(excinfo);
2886
0
        }
2887
0
        xi_error_clear(&err);
2888
0
    }
2889
0
    return res;
2890
0
}
2891
2892
2893
/* in an active cross-interpreter session */
2894
2895
static const char *
2896
capture_session_error(_PyXI_session *session, _PyXI_error *err,
2897
                      _PyXI_failure *override)
2898
0
{
2899
0
    assert(_session_is_active(session));
2900
0
    assert(!xi_error_is_set(err));
2901
0
    PyThreadState *tstate = session->init_tstate;
2902
2903
    // Normalize the exception override.
2904
0
    if (override != NULL) {
2905
0
        if (override->code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
2906
0
            assert(override->msg == NULL);
2907
0
            override = NULL;
2908
0
        }
2909
0
        else {
2910
0
            assert(override->code != _PyXI_ERR_NO_ERROR);
2911
0
        }
2912
0
    }
2913
2914
    // Handle the exception, if any.
2915
0
    const char *failure = NULL;
2916
0
    PyObject *exc = xi_error_resolve_current_exc(tstate, override);
2917
0
    if (exc != NULL) {
2918
        // There is an unhandled exception we need to preserve.
2919
0
        failure = xi_error_set_exc(tstate, err, exc);
2920
0
        Py_DECREF(exc);
2921
0
        if (_PyErr_Occurred(tstate)) {
2922
0
            PyErr_FormatUnraisable(failure);
2923
0
        }
2924
0
    }
2925
2926
    // Handle the override.
2927
0
    if (override != NULL && failure == NULL) {
2928
0
        xi_error_set_override(tstate, err, override);
2929
0
    }
2930
2931
    // Finished!
2932
0
    assert(!_PyErr_Occurred(tstate));
2933
0
    return failure;
2934
0
}
2935
2936
static int
2937
_ensure_main_ns(_PyXI_session *session, _PyXI_failure *failure)
2938
0
{
2939
0
    assert(_session_is_active(session));
2940
0
    PyThreadState *tstate = session->init_tstate;
2941
0
    if (session->main_ns != NULL) {
2942
0
        return 0;
2943
0
    }
2944
    // Cache __main__.__dict__.
2945
0
    PyObject *main_mod = _Py_GetMainModule(tstate);
2946
0
    if (_Py_CheckMainModule(main_mod) < 0) {
2947
0
        Py_XDECREF(main_mod);
2948
0
        if (failure != NULL) {
2949
0
            *failure = (_PyXI_failure){
2950
0
                .code = _PyXI_ERR_MAIN_NS_FAILURE,
2951
0
            };
2952
0
        }
2953
0
        return -1;
2954
0
    }
2955
0
    PyObject *ns = PyModule_GetDict(main_mod);  // borrowed
2956
0
    Py_DECREF(main_mod);
2957
0
    if (ns == NULL) {
2958
0
        if (failure != NULL) {
2959
0
            *failure = (_PyXI_failure){
2960
0
                .code = _PyXI_ERR_MAIN_NS_FAILURE,
2961
0
            };
2962
0
        }
2963
0
        return -1;
2964
0
    }
2965
0
    session->main_ns = Py_NewRef(ns);
2966
0
    return 0;
2967
0
}
2968
2969
PyObject *
2970
_PyXI_GetMainNamespace(_PyXI_session *session, _PyXI_failure *failure)
2971
0
{
2972
0
    if (!_session_is_active(session)) {
2973
0
        PyErr_SetString(PyExc_RuntimeError, "session not active");
2974
0
        return NULL;
2975
0
    }
2976
0
    if (_ensure_main_ns(session, failure) < 0) {
2977
0
        return NULL;
2978
0
    }
2979
0
    return session->main_ns;
2980
0
}
2981
2982
2983
static int
2984
_pop_preserved(_PyXI_session *session,
2985
               _PyXI_namespace **p_xidata, PyObject **p_obj,
2986
               _PyXI_failure *p_failure)
2987
0
{
2988
0
    _PyXI_failure failure = XI_FAILURE_INIT;
2989
0
    _PyXI_namespace *xidata = NULL;
2990
0
    assert(_PyThreadState_GET() == session->init_tstate);  // active session
2991
2992
0
    if (session->_preserved == NULL) {
2993
0
        *p_xidata = NULL;
2994
0
        *p_obj = NULL;
2995
0
        return 0;
2996
0
    }
2997
0
    if (session->init_tstate == session->prev_tstate) {
2998
        // We did not switch interpreters.
2999
0
        *p_xidata = NULL;
3000
0
        *p_obj = session->_preserved;
3001
0
        session->_preserved = NULL;
3002
0
        return 0;
3003
0
    }
3004
0
    *p_obj = NULL;
3005
3006
    // We did switch interpreters.
3007
0
    Py_ssize_t len = PyDict_Size(session->_preserved);
3008
0
    if (len < 0) {
3009
0
        failure.code = _PyXI_ERR_PRESERVE_FAILURE;
3010
0
        goto error;
3011
0
    }
3012
0
    else if (len == 0) {
3013
0
        *p_xidata = NULL;
3014
0
    }
3015
0
    else {
3016
0
        xidata = _create_sharedns(session->_preserved);
3017
0
        if (xidata == NULL) {
3018
0
            failure.code = _PyXI_ERR_PRESERVE_FAILURE;
3019
0
            goto error;
3020
0
        }
3021
0
        if (_fill_sharedns(xidata, session->_preserved,
3022
0
                           _PyXIDATA_FULL_FALLBACK, &failure) < 0)
3023
0
        {
3024
0
            if (failure.code != _PyXI_ERR_NOT_SHAREABLE) {
3025
0
                assert(failure.msg != NULL);
3026
0
                failure.code = _PyXI_ERR_PRESERVE_FAILURE;
3027
0
            }
3028
0
            goto error;
3029
0
        }
3030
0
        *p_xidata = xidata;
3031
0
    }
3032
0
    Py_CLEAR(session->_preserved);
3033
0
    return 0;
3034
3035
0
error:
3036
0
    if (p_failure != NULL) {
3037
0
        *p_failure = failure;
3038
0
    }
3039
0
    if (xidata != NULL) {
3040
0
        _destroy_sharedns(xidata);
3041
0
    }
3042
0
    return -1;
3043
0
}
3044
3045
static int
3046
_finish_preserved(_PyXI_namespace *xidata, PyObject **p_preserved)
3047
0
{
3048
0
    if (xidata == NULL) {
3049
0
        return 0;
3050
0
    }
3051
0
    int res = -1;
3052
0
    if (p_preserved != NULL) {
3053
0
        PyObject *ns = PyDict_New();
3054
0
        if (ns == NULL) {
3055
0
            goto finally;
3056
0
        }
3057
0
        if (_apply_sharedns(xidata, ns, NULL) < 0) {
3058
0
            Py_CLEAR(ns);
3059
0
            goto finally;
3060
0
        }
3061
0
        *p_preserved = ns;
3062
0
    }
3063
0
    res = 0;
3064
3065
0
finally:
3066
0
    _destroy_sharedns(xidata);
3067
0
    return res;
3068
0
}
3069
3070
int
3071
_PyXI_Preserve(_PyXI_session *session, const char *name, PyObject *value,
3072
               _PyXI_failure *p_failure)
3073
0
{
3074
0
    _PyXI_failure failure = XI_FAILURE_INIT;
3075
0
    if (!_session_is_active(session)) {
3076
0
        PyErr_SetString(PyExc_RuntimeError, "session not active");
3077
0
        return -1;
3078
0
    }
3079
0
    if (session->_preserved == NULL) {
3080
0
        session->_preserved = PyDict_New();
3081
0
        if (session->_preserved == NULL) {
3082
0
            set_exc_with_cause(PyExc_RuntimeError,
3083
0
                               "failed to initialize preserved objects");
3084
0
            failure.code = _PyXI_ERR_PRESERVE_FAILURE;
3085
0
            goto error;
3086
0
        }
3087
0
    }
3088
0
    if (PyDict_SetItemString(session->_preserved, name, value) < 0) {
3089
0
        set_exc_with_cause(PyExc_RuntimeError, "failed to preserve object");
3090
0
        failure.code = _PyXI_ERR_PRESERVE_FAILURE;
3091
0
        goto error;
3092
0
    }
3093
0
    return 0;
3094
3095
0
error:
3096
0
    if (p_failure != NULL) {
3097
0
        *p_failure = failure;
3098
0
    }
3099
0
    return -1;
3100
0
}
3101
3102
PyObject *
3103
_PyXI_GetPreserved(_PyXI_session_result *result, const char *name)
3104
0
{
3105
0
    PyObject *value = NULL;
3106
0
    if (result->preserved != NULL) {
3107
0
        (void)PyDict_GetItemStringRef(result->preserved, name, &value);
3108
0
    }
3109
0
    return value;
3110
0
}
3111
3112
void
3113
_PyXI_ClearResult(_PyXI_session_result *result)
3114
0
{
3115
0
    Py_CLEAR(result->preserved);
3116
0
    Py_CLEAR(result->excinfo);
3117
0
}
3118
3119
3120
/*********************/
3121
/* runtime lifecycle */
3122
/*********************/
3123
3124
int
3125
_Py_xi_global_state_init(_PyXI_global_state_t *state)
3126
37
{
3127
37
    assert(state != NULL);
3128
37
    xid_lookup_init(&state->data_lookup);
3129
37
    return 0;
3130
37
}
3131
3132
void
3133
_Py_xi_global_state_fini(_PyXI_global_state_t *state)
3134
0
{
3135
0
    assert(state != NULL);
3136
0
    xid_lookup_fini(&state->data_lookup);
3137
0
}
3138
3139
int
3140
_Py_xi_state_init(_PyXI_state_t *state, PyInterpreterState *interp)
3141
37
{
3142
37
    assert(state != NULL);
3143
37
    assert(interp == NULL || state == _PyXI_GET_STATE(interp));
3144
3145
    // Initialize pickle function cache (before any fallible ops).
3146
37
    state->pickle.dumps = NULL;
3147
37
    state->pickle.loads = NULL;
3148
3149
37
    xid_lookup_init(&state->data_lookup);
3150
3151
    // Initialize exceptions.
3152
37
    if (interp != NULL) {
3153
0
        if (init_static_exctypes(&state->exceptions, interp) < 0) {
3154
0
            fini_heap_exctypes(&state->exceptions);
3155
0
            return -1;
3156
0
        }
3157
0
    }
3158
37
    if (init_heap_exctypes(&state->exceptions) < 0) {
3159
0
        return -1;
3160
0
    }
3161
3162
37
    return 0;
3163
37
}
3164
3165
void
3166
_Py_xi_state_fini(_PyXI_state_t *state, PyInterpreterState *interp)
3167
0
{
3168
0
    assert(state != NULL);
3169
0
    assert(interp == NULL || state == _PyXI_GET_STATE(interp));
3170
3171
    // Clear pickle function cache first: the cached functions may hold
3172
    // references to modules cleaned up by later finalization steps.
3173
0
    Py_CLEAR(state->pickle.dumps);
3174
0
    Py_CLEAR(state->pickle.loads);
3175
3176
0
    fini_heap_exctypes(&state->exceptions);
3177
0
    if (interp != NULL) {
3178
0
        fini_static_exctypes(&state->exceptions, interp);
3179
0
    }
3180
3181
0
    xid_lookup_fini(&state->data_lookup);
3182
0
}
3183
3184
3185
PyStatus
3186
_PyXI_Init(PyInterpreterState *interp)
3187
37
{
3188
37
    if (_Py_IsMainInterpreter(interp)) {
3189
37
        _PyXI_global_state_t *global_state = _PyXI_GET_GLOBAL_STATE(interp);
3190
37
        if (global_state == NULL) {
3191
0
            PyErr_PrintEx(0);
3192
0
            return _PyStatus_ERR(
3193
0
                    "failed to get global cross-interpreter state");
3194
0
        }
3195
37
        if (_Py_xi_global_state_init(global_state) < 0) {
3196
0
            PyErr_PrintEx(0);
3197
0
            return _PyStatus_ERR(
3198
0
                    "failed to initialize  global cross-interpreter state");
3199
0
        }
3200
37
    }
3201
3202
37
    _PyXI_state_t *state = _PyXI_GET_STATE(interp);
3203
37
    if (state == NULL) {
3204
0
        PyErr_PrintEx(0);
3205
0
        return _PyStatus_ERR(
3206
0
                "failed to get interpreter's cross-interpreter state");
3207
0
    }
3208
    // The static types were already initialized in _PyXI_InitTypes(),
3209
    // so we pass in NULL here to avoid initializing them again.
3210
37
    if (_Py_xi_state_init(state, NULL) < 0) {
3211
0
        PyErr_PrintEx(0);
3212
0
        return _PyStatus_ERR(
3213
0
                "failed to initialize interpreter's cross-interpreter state");
3214
0
    }
3215
3216
37
    return _PyStatus_OK();
3217
37
}
3218
3219
// _PyXI_Fini() must be called before the interpreter is cleared,
3220
// since we must clear some heap objects.
3221
3222
void
3223
_PyXI_Fini(PyInterpreterState *interp)
3224
0
{
3225
0
    _PyXI_state_t *state = _PyXI_GET_STATE(interp);
3226
#ifndef NDEBUG
3227
    if (state == NULL) {
3228
        PyErr_PrintEx(0);
3229
        return;
3230
    }
3231
#endif
3232
    // The static types will be finalized soon in _PyXI_FiniTypes(),
3233
    // so we pass in NULL here to avoid finalizing them right now.
3234
0
    _Py_xi_state_fini(state, NULL);
3235
3236
0
    if (_Py_IsMainInterpreter(interp)) {
3237
0
        _PyXI_global_state_t *global_state = _PyXI_GET_GLOBAL_STATE(interp);
3238
0
        _Py_xi_global_state_fini(global_state);
3239
0
    }
3240
0
}
3241
3242
PyStatus
3243
_PyXI_InitTypes(PyInterpreterState *interp)
3244
37
{
3245
37
    if (init_static_exctypes(&_PyXI_GET_STATE(interp)->exceptions, interp) < 0) {
3246
0
        PyErr_PrintEx(0);
3247
0
        return _PyStatus_ERR(
3248
0
                "failed to initialize the cross-interpreter exception types");
3249
0
    }
3250
    // We would initialize heap types here too but that leads to ref leaks.
3251
    // Instead, we initialize them in _PyXI_Init().
3252
37
    return _PyStatus_OK();
3253
37
}
3254
3255
void
3256
_PyXI_FiniTypes(PyInterpreterState *interp)
3257
0
{
3258
    // We would finalize heap types here too but that leads to ref leaks.
3259
    // Instead, we finalize them in _PyXI_Fini().
3260
0
    fini_static_exctypes(&_PyXI_GET_STATE(interp)->exceptions, interp);
3261
0
}
3262
3263
3264
/*************/
3265
/* other API */
3266
/*************/
3267
3268
PyInterpreterState *
3269
_PyXI_NewInterpreter(PyInterpreterConfig *config, long *maybe_whence,
3270
                     PyThreadState **p_tstate, PyThreadState **p_save_tstate)
3271
0
{
3272
0
    PyThreadState *save_tstate = PyThreadState_Swap(NULL);
3273
0
    assert(save_tstate != NULL);
3274
3275
0
    PyThreadState *tstate;
3276
0
    PyStatus status = Py_NewInterpreterFromConfig(&tstate, config);
3277
0
    if (PyStatus_Exception(status)) {
3278
        // Since no new thread state was created, there is no exception
3279
        // to propagate; raise a fresh one after swapping back in the
3280
        // old thread state.
3281
0
        PyThreadState_Swap(save_tstate);
3282
0
        _PyErr_SetFromPyStatus(status);
3283
0
        PyObject *exc = PyErr_GetRaisedException();
3284
0
        PyErr_SetString(PyExc_InterpreterError,
3285
0
                        "sub-interpreter creation failed");
3286
0
        _PyErr_ChainExceptions1(exc);
3287
0
        return NULL;
3288
0
    }
3289
0
    assert(tstate != NULL);
3290
0
    PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
3291
3292
0
    long whence = _PyInterpreterState_WHENCE_XI;
3293
0
    if (maybe_whence != NULL) {
3294
0
        whence = *maybe_whence;
3295
0
    }
3296
0
    _PyInterpreterState_SetWhence(interp, whence);
3297
3298
0
    if (p_tstate != NULL) {
3299
        // We leave the new thread state as the current one.
3300
0
        *p_tstate = tstate;
3301
0
    }
3302
0
    else {
3303
        // Throw away the initial tstate.
3304
0
        PyThreadState_Clear(tstate);
3305
0
        PyThreadState_Swap(save_tstate);
3306
0
        PyThreadState_Delete(tstate);
3307
0
        save_tstate = NULL;
3308
0
    }
3309
0
    if (p_save_tstate != NULL) {
3310
0
        *p_save_tstate = save_tstate;
3311
0
    }
3312
0
    return interp;
3313
0
}
3314
3315
void
3316
_PyXI_EndInterpreter(PyInterpreterState *interp,
3317
                     PyThreadState *tstate, PyThreadState **p_save_tstate)
3318
0
{
3319
#ifndef NDEBUG
3320
    long whence = _PyInterpreterState_GetWhence(interp);
3321
#endif
3322
0
    assert(whence != _PyInterpreterState_WHENCE_RUNTIME);
3323
3324
0
    if (!_PyInterpreterState_IsReady(interp)) {
3325
0
        assert(whence == _PyInterpreterState_WHENCE_UNKNOWN);
3326
        // PyInterpreterState_Clear() requires the GIL,
3327
        // which a not-ready does not have, so we don't clear it.
3328
        // That means there may be leaks here until clearing the
3329
        // interpreter is fixed.
3330
0
        PyInterpreterState_Delete(interp);
3331
0
        return;
3332
0
    }
3333
0
    assert(whence != _PyInterpreterState_WHENCE_UNKNOWN);
3334
3335
0
    PyThreadState *save_tstate = NULL;
3336
0
    PyThreadState *cur_tstate = PyThreadState_GET();
3337
0
    if (tstate == NULL) {
3338
0
        if (PyThreadState_GetInterpreter(cur_tstate) == interp) {
3339
0
            tstate = cur_tstate;
3340
0
        }
3341
0
        else {
3342
0
            tstate = _PyThreadState_NewBound(interp, _PyThreadState_WHENCE_FINI);
3343
0
            assert(tstate != NULL);
3344
0
            save_tstate = PyThreadState_Swap(tstate);
3345
0
        }
3346
0
    }
3347
0
    else {
3348
0
        assert(PyThreadState_GetInterpreter(tstate) == interp);
3349
0
        if (tstate != cur_tstate) {
3350
0
            assert(PyThreadState_GetInterpreter(cur_tstate) != interp);
3351
0
            save_tstate = PyThreadState_Swap(tstate);
3352
0
        }
3353
0
    }
3354
3355
0
    Py_EndInterpreter(tstate);
3356
3357
0
    if (p_save_tstate != NULL) {
3358
0
        save_tstate = *p_save_tstate;
3359
0
    }
3360
0
    PyThreadState_Swap(save_tstate);
3361
0
}