Branch data Line data Source code
1 : :
2 : : /* interpreters module */
3 : : /* low-level access to interpreter primitives */
4 : : #ifndef Py_BUILD_CORE_BUILTIN
5 : : # define Py_BUILD_CORE_MODULE 1
6 : : #endif
7 : :
8 : : #include "Python.h"
9 : : // XXX This module should not rely on internal API.
10 : : #include "pycore_frame.h"
11 : : #include "pycore_pystate.h" // _PyThreadState_GET()
12 : : #include "pycore_interpreteridobject.h"
13 : :
14 : :
15 : : #define MODULE_NAME "_xxsubinterpreters"
16 : :
17 : :
18 : : static const char *
19 : 0 : _copy_raw_string(PyObject *strobj)
20 : : {
21 : 0 : const char *str = PyUnicode_AsUTF8(strobj);
22 [ # # ]: 0 : if (str == NULL) {
23 : 0 : return NULL;
24 : : }
25 : 0 : char *copied = PyMem_RawMalloc(strlen(str)+1);
26 [ # # ]: 0 : if (copied == NULL) {
27 : 0 : PyErr_NoMemory();
28 : 0 : return NULL;
29 : : }
30 : 0 : strcpy(copied, str);
31 : 0 : return copied;
32 : : }
33 : :
34 : : static PyInterpreterState *
35 : 0 : _get_current_interp(void)
36 : : {
37 : : // PyInterpreterState_Get() aborts if lookup fails, so don't need
38 : : // to check the result for NULL.
39 : 0 : return PyInterpreterState_Get();
40 : : }
41 : :
42 : : static PyObject *
43 : 1 : add_new_exception(PyObject *mod, const char *name, PyObject *base)
44 : : {
45 : : assert(!PyObject_HasAttrString(mod, name));
46 : 1 : PyObject *exctype = PyErr_NewException(name, base, NULL);
47 [ - + ]: 1 : if (exctype == NULL) {
48 : 0 : return NULL;
49 : : }
50 : 1 : int res = PyModule_AddType(mod, (PyTypeObject *)exctype);
51 [ - + ]: 1 : if (res < 0) {
52 : 0 : Py_DECREF(exctype);
53 : 0 : return NULL;
54 : : }
55 : 1 : return exctype;
56 : : }
57 : :
58 : : #define ADD_NEW_EXCEPTION(MOD, NAME, BASE) \
59 : : add_new_exception(MOD, MODULE_NAME "." Py_STRINGIFY(NAME), BASE)
60 : :
61 : : static int
62 : 0 : _release_xid_data(_PyCrossInterpreterData *data, int ignoreexc)
63 : : {
64 : : PyObject *exc;
65 [ # # ]: 0 : if (ignoreexc) {
66 : 0 : exc = PyErr_GetRaisedException();
67 : : }
68 : 0 : int res = _PyCrossInterpreterData_Release(data);
69 [ # # ]: 0 : if (res < 0) {
70 : : // XXX Fix this!
71 : : /* The owning interpreter is already destroyed.
72 : : * Ideally, this shouldn't ever happen. (It's highly unlikely.)
73 : : * For now we hack around that to resolve refleaks, by decref'ing
74 : : * the released object here, even if its the wrong interpreter.
75 : : * The owning interpreter has already been destroyed
76 : : * so we should be okay, especially since the currently
77 : : * shareable types are all very basic, with no GC.
78 : : * That said, it becomes much messier once interpreters
79 : : * no longer share a GIL, so this needs to be fixed before then. */
80 : 0 : _PyCrossInterpreterData_Clear(NULL, data);
81 [ # # ]: 0 : if (ignoreexc) {
82 : : // XXX Emit a warning?
83 : 0 : PyErr_Clear();
84 : : }
85 : : }
86 [ # # ]: 0 : if (ignoreexc) {
87 : 0 : PyErr_SetRaisedException(exc);
88 : : }
89 : 0 : return res;
90 : : }
91 : :
92 : :
93 : : /* module state *************************************************************/
94 : :
95 : : typedef struct {
96 : : /* exceptions */
97 : : PyObject *RunFailedError;
98 : : } module_state;
99 : :
100 : : static inline module_state *
101 : 9 : get_module_state(PyObject *mod)
102 : : {
103 : : assert(mod != NULL);
104 : 9 : module_state *state = PyModule_GetState(mod);
105 : : assert(state != NULL);
106 : 9 : return state;
107 : : }
108 : :
109 : : static int
110 : 6 : traverse_module_state(module_state *state, visitproc visit, void *arg)
111 : : {
112 : : /* exceptions */
113 [ + - - + ]: 6 : Py_VISIT(state->RunFailedError);
114 : :
115 : 6 : return 0;
116 : : }
117 : :
118 : : static int
119 : 2 : clear_module_state(module_state *state)
120 : : {
121 : : /* exceptions */
122 [ + + ]: 2 : Py_CLEAR(state->RunFailedError);
123 : :
124 : 2 : return 0;
125 : : }
126 : :
127 : :
128 : : /* data-sharing-specific code ***********************************************/
129 : :
130 : : struct _sharednsitem {
131 : : const char *name;
132 : : _PyCrossInterpreterData data;
133 : : };
134 : :
135 : : static void _sharednsitem_clear(struct _sharednsitem *); // forward
136 : :
137 : : static int
138 : 0 : _sharednsitem_init(struct _sharednsitem *item, PyObject *key, PyObject *value)
139 : : {
140 : 0 : item->name = _copy_raw_string(key);
141 [ # # ]: 0 : if (item->name == NULL) {
142 : 0 : return -1;
143 : : }
144 [ # # ]: 0 : if (_PyObject_GetCrossInterpreterData(value, &item->data) != 0) {
145 : 0 : _sharednsitem_clear(item);
146 : 0 : return -1;
147 : : }
148 : 0 : return 0;
149 : : }
150 : :
151 : : static void
152 : 0 : _sharednsitem_clear(struct _sharednsitem *item)
153 : : {
154 [ # # ]: 0 : if (item->name != NULL) {
155 : 0 : PyMem_RawFree((void *)item->name);
156 : 0 : item->name = NULL;
157 : : }
158 : 0 : (void)_release_xid_data(&item->data, 1);
159 : 0 : }
160 : :
161 : : static int
162 : 0 : _sharednsitem_apply(struct _sharednsitem *item, PyObject *ns)
163 : : {
164 : 0 : PyObject *name = PyUnicode_FromString(item->name);
165 [ # # ]: 0 : if (name == NULL) {
166 : 0 : return -1;
167 : : }
168 : 0 : PyObject *value = _PyCrossInterpreterData_NewObject(&item->data);
169 [ # # ]: 0 : if (value == NULL) {
170 : 0 : Py_DECREF(name);
171 : 0 : return -1;
172 : : }
173 : 0 : int res = PyDict_SetItem(ns, name, value);
174 : 0 : Py_DECREF(name);
175 : 0 : Py_DECREF(value);
176 : 0 : return res;
177 : : }
178 : :
179 : : typedef struct _sharedns {
180 : : Py_ssize_t len;
181 : : struct _sharednsitem* items;
182 : : } _sharedns;
183 : :
184 : : static _sharedns *
185 : 0 : _sharedns_new(Py_ssize_t len)
186 : : {
187 : 0 : _sharedns *shared = PyMem_NEW(_sharedns, 1);
188 [ # # ]: 0 : if (shared == NULL) {
189 : 0 : PyErr_NoMemory();
190 : 0 : return NULL;
191 : : }
192 : 0 : shared->len = len;
193 [ # # ]: 0 : shared->items = PyMem_NEW(struct _sharednsitem, len);
194 [ # # ]: 0 : if (shared->items == NULL) {
195 : 0 : PyErr_NoMemory();
196 : 0 : PyMem_Free(shared);
197 : 0 : return NULL;
198 : : }
199 : 0 : return shared;
200 : : }
201 : :
202 : : static void
203 : 0 : _sharedns_free(_sharedns *shared)
204 : : {
205 [ # # ]: 0 : for (Py_ssize_t i=0; i < shared->len; i++) {
206 : 0 : _sharednsitem_clear(&shared->items[i]);
207 : : }
208 : 0 : PyMem_Free(shared->items);
209 : 0 : PyMem_Free(shared);
210 : 0 : }
211 : :
212 : : static _sharedns *
213 : 0 : _get_shared_ns(PyObject *shareable)
214 : : {
215 [ # # # # ]: 0 : if (shareable == NULL || shareable == Py_None) {
216 : 0 : return NULL;
217 : : }
218 : 0 : Py_ssize_t len = PyDict_Size(shareable);
219 [ # # ]: 0 : if (len == 0) {
220 : 0 : return NULL;
221 : : }
222 : :
223 : 0 : _sharedns *shared = _sharedns_new(len);
224 [ # # ]: 0 : if (shared == NULL) {
225 : 0 : return NULL;
226 : : }
227 : 0 : Py_ssize_t pos = 0;
228 [ # # ]: 0 : for (Py_ssize_t i=0; i < len; i++) {
229 : : PyObject *key, *value;
230 [ # # ]: 0 : if (PyDict_Next(shareable, &pos, &key, &value) == 0) {
231 : 0 : break;
232 : : }
233 [ # # ]: 0 : if (_sharednsitem_init(&shared->items[i], key, value) != 0) {
234 : 0 : break;
235 : : }
236 : : }
237 [ # # ]: 0 : if (PyErr_Occurred()) {
238 : 0 : _sharedns_free(shared);
239 : 0 : return NULL;
240 : : }
241 : 0 : return shared;
242 : : }
243 : :
244 : : static int
245 : 0 : _sharedns_apply(_sharedns *shared, PyObject *ns)
246 : : {
247 [ # # ]: 0 : for (Py_ssize_t i=0; i < shared->len; i++) {
248 [ # # ]: 0 : if (_sharednsitem_apply(&shared->items[i], ns) != 0) {
249 : 0 : return -1;
250 : : }
251 : : }
252 : 0 : return 0;
253 : : }
254 : :
255 : : // Ultimately we'd like to preserve enough information about the
256 : : // exception and traceback that we could re-constitute (or at least
257 : : // simulate, a la traceback.TracebackException), and even chain, a copy
258 : : // of the exception in the calling interpreter.
259 : :
260 : : typedef struct _sharedexception {
261 : : const char *name;
262 : : const char *msg;
263 : : } _sharedexception;
264 : :
265 : : static const struct _sharedexception no_exception = {
266 : : .name = NULL,
267 : : .msg = NULL,
268 : : };
269 : :
270 : : static void
271 : 0 : _sharedexception_clear(_sharedexception *exc)
272 : : {
273 [ # # ]: 0 : if (exc->name != NULL) {
274 : 0 : PyMem_RawFree((void *)exc->name);
275 : : }
276 [ # # ]: 0 : if (exc->msg != NULL) {
277 : 0 : PyMem_RawFree((void *)exc->msg);
278 : : }
279 : 0 : }
280 : :
281 : : static const char *
282 : 0 : _sharedexception_bind(PyObject *exc, _sharedexception *sharedexc)
283 : : {
284 : : assert(exc != NULL);
285 : 0 : const char *failure = NULL;
286 : :
287 : 0 : PyObject *nameobj = PyUnicode_FromFormat("%S", Py_TYPE(exc));
288 [ # # ]: 0 : if (nameobj == NULL) {
289 : 0 : failure = "unable to format exception type name";
290 : 0 : goto error;
291 : : }
292 : 0 : sharedexc->name = _copy_raw_string(nameobj);
293 : 0 : Py_DECREF(nameobj);
294 [ # # ]: 0 : if (sharedexc->name == NULL) {
295 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
296 : 0 : failure = "out of memory copying exception type name";
297 : : } else {
298 : 0 : failure = "unable to encode and copy exception type name";
299 : : }
300 : 0 : goto error;
301 : : }
302 : :
303 [ # # ]: 0 : if (exc != NULL) {
304 : 0 : PyObject *msgobj = PyUnicode_FromFormat("%S", exc);
305 [ # # ]: 0 : if (msgobj == NULL) {
306 : 0 : failure = "unable to format exception message";
307 : 0 : goto error;
308 : : }
309 : 0 : sharedexc->msg = _copy_raw_string(msgobj);
310 : 0 : Py_DECREF(msgobj);
311 [ # # ]: 0 : if (sharedexc->msg == NULL) {
312 [ # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
313 : 0 : failure = "out of memory copying exception message";
314 : : } else {
315 : 0 : failure = "unable to encode and copy exception message";
316 : : }
317 : 0 : goto error;
318 : : }
319 : : }
320 : :
321 : 0 : return NULL;
322 : :
323 : 0 : error:
324 : : assert(failure != NULL);
325 : 0 : PyErr_Clear();
326 : 0 : _sharedexception_clear(sharedexc);
327 : 0 : *sharedexc = no_exception;
328 : 0 : return failure;
329 : : }
330 : :
331 : : static void
332 : 0 : _sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass)
333 : : {
334 [ # # ]: 0 : if (exc->name != NULL) {
335 [ # # ]: 0 : if (exc->msg != NULL) {
336 : 0 : PyErr_Format(wrapperclass, "%s: %s", exc->name, exc->msg);
337 : : }
338 : : else {
339 : 0 : PyErr_SetString(wrapperclass, exc->name);
340 : : }
341 : : }
342 [ # # ]: 0 : else if (exc->msg != NULL) {
343 : 0 : PyErr_SetString(wrapperclass, exc->msg);
344 : : }
345 : : else {
346 : 0 : PyErr_SetNone(wrapperclass);
347 : : }
348 : 0 : }
349 : :
350 : :
351 : : /* interpreter-specific code ************************************************/
352 : :
353 : : static int
354 : 1 : exceptions_init(PyObject *mod)
355 : : {
356 : 1 : module_state *state = get_module_state(mod);
357 [ - + ]: 1 : if (state == NULL) {
358 : 0 : return -1;
359 : : }
360 : :
361 : : #define ADD(NAME, BASE) \
362 : : do { \
363 : : assert(state->NAME == NULL); \
364 : : state->NAME = ADD_NEW_EXCEPTION(mod, NAME, BASE); \
365 : : if (state->NAME == NULL) { \
366 : : return -1; \
367 : : } \
368 : : } while (0)
369 : :
370 : : // An uncaught exception came out of interp_run_string().
371 [ - + ]: 1 : ADD(RunFailedError, PyExc_RuntimeError);
372 : : #undef ADD
373 : :
374 : 1 : return 0;
375 : : }
376 : :
377 : : static int
378 : 0 : _is_running(PyInterpreterState *interp)
379 : : {
380 : 0 : PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
381 [ # # ]: 0 : if (PyThreadState_Next(tstate) != NULL) {
382 : 0 : PyErr_SetString(PyExc_RuntimeError,
383 : : "interpreter has more than one thread");
384 : 0 : return -1;
385 : : }
386 : :
387 : : assert(!PyErr_Occurred());
388 : 0 : _PyInterpreterFrame *frame = tstate->cframe->current_frame;
389 [ # # ]: 0 : if (frame == NULL) {
390 : 0 : return 0;
391 : : }
392 : 0 : return 1;
393 : : }
394 : :
395 : : static int
396 : 0 : _ensure_not_running(PyInterpreterState *interp)
397 : : {
398 : 0 : int is_running = _is_running(interp);
399 [ # # ]: 0 : if (is_running < 0) {
400 : 0 : return -1;
401 : : }
402 [ # # ]: 0 : if (is_running) {
403 : 0 : PyErr_Format(PyExc_RuntimeError, "interpreter already running");
404 : 0 : return -1;
405 : : }
406 : 0 : return 0;
407 : : }
408 : :
409 : : static int
410 : 0 : _run_script(PyInterpreterState *interp, const char *codestr,
411 : : _sharedns *shared, _sharedexception *sharedexc)
412 : : {
413 : 0 : PyObject *excval = NULL;
414 : 0 : PyObject *main_mod = _PyInterpreterState_GetMainModule(interp);
415 [ # # ]: 0 : if (main_mod == NULL) {
416 : 0 : goto error;
417 : : }
418 : 0 : PyObject *ns = PyModule_GetDict(main_mod); // borrowed
419 : 0 : Py_DECREF(main_mod);
420 [ # # ]: 0 : if (ns == NULL) {
421 : 0 : goto error;
422 : : }
423 : 0 : Py_INCREF(ns);
424 : :
425 : : // Apply the cross-interpreter data.
426 [ # # ]: 0 : if (shared != NULL) {
427 [ # # ]: 0 : if (_sharedns_apply(shared, ns) != 0) {
428 : 0 : Py_DECREF(ns);
429 : 0 : goto error;
430 : : }
431 : : }
432 : :
433 : : // Run the string (see PyRun_SimpleStringFlags).
434 : 0 : PyObject *result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL);
435 : 0 : Py_DECREF(ns);
436 [ # # ]: 0 : if (result == NULL) {
437 : 0 : goto error;
438 : : }
439 : : else {
440 : 0 : Py_DECREF(result); // We throw away the result.
441 : : }
442 : :
443 : 0 : *sharedexc = no_exception;
444 : 0 : return 0;
445 : :
446 : 0 : error:
447 : 0 : excval = PyErr_GetRaisedException();
448 : 0 : const char *failure = _sharedexception_bind(excval, sharedexc);
449 [ # # ]: 0 : if (failure != NULL) {
450 : 0 : fprintf(stderr,
451 : : "RunFailedError: script raised an uncaught exception (%s)",
452 : : failure);
453 : 0 : PyErr_Clear();
454 : : }
455 : 0 : Py_XDECREF(excval);
456 : : assert(!PyErr_Occurred());
457 : 0 : return -1;
458 : : }
459 : :
460 : : static int
461 : 0 : _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp,
462 : : const char *codestr, PyObject *shareables)
463 : : {
464 [ # # ]: 0 : if (_ensure_not_running(interp) < 0) {
465 : 0 : return -1;
466 : : }
467 : 0 : module_state *state = get_module_state(mod);
468 : :
469 : 0 : _sharedns *shared = _get_shared_ns(shareables);
470 [ # # # # ]: 0 : if (shared == NULL && PyErr_Occurred()) {
471 : 0 : return -1;
472 : : }
473 : :
474 : : // Switch to interpreter.
475 : 0 : PyThreadState *save_tstate = NULL;
476 [ # # ]: 0 : if (interp != PyInterpreterState_Get()) {
477 : : // XXX Using the "head" thread isn't strictly correct.
478 : 0 : PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
479 : : // XXX Possible GILState issues?
480 : 0 : save_tstate = PyThreadState_Swap(tstate);
481 : : }
482 : :
483 : : // Run the script.
484 : : _sharedexception exc;
485 : 0 : int result = _run_script(interp, codestr, shared, &exc);
486 : :
487 : : // Switch back.
488 [ # # ]: 0 : if (save_tstate != NULL) {
489 : 0 : PyThreadState_Swap(save_tstate);
490 : : }
491 : :
492 : : // Propagate any exception out to the caller.
493 [ # # ]: 0 : if (exc.name != NULL) {
494 : : assert(state != NULL);
495 : 0 : _sharedexception_apply(&exc, state->RunFailedError);
496 : : }
497 [ # # ]: 0 : else if (result != 0) {
498 : : // We were unable to allocate a shared exception.
499 : 0 : PyErr_NoMemory();
500 : : }
501 : :
502 [ # # ]: 0 : if (shared != NULL) {
503 : 0 : _sharedns_free(shared);
504 : : }
505 : :
506 : 0 : return result;
507 : : }
508 : :
509 : :
510 : : /* module level code ********************************************************/
511 : :
512 : : static PyObject *
513 : 0 : interp_create(PyObject *self, PyObject *args, PyObject *kwds)
514 : : {
515 : :
516 : : static char *kwlist[] = {"isolated", NULL};
517 : 0 : int isolated = 1;
518 [ # # ]: 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$i:create", kwlist,
519 : : &isolated)) {
520 : 0 : return NULL;
521 : : }
522 : :
523 : : // Create and initialize the new interpreter.
524 : 0 : PyThreadState *save_tstate = _PyThreadState_GET();
525 : 0 : const _PyInterpreterConfig config = isolated
526 [ # # ]: 0 : ? (_PyInterpreterConfig)_PyInterpreterConfig_INIT
527 : : : (_PyInterpreterConfig)_PyInterpreterConfig_LEGACY_INIT;
528 : : // XXX Possible GILState issues?
529 : 0 : PyThreadState *tstate = _Py_NewInterpreterFromConfig(&config);
530 : 0 : PyThreadState_Swap(save_tstate);
531 [ # # ]: 0 : if (tstate == NULL) {
532 : : /* Since no new thread state was created, there is no exception to
533 : : propagate; raise a fresh one after swapping in the old thread
534 : : state. */
535 : 0 : PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed");
536 : 0 : return NULL;
537 : : }
538 : 0 : PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
539 : 0 : PyObject *idobj = _PyInterpreterState_GetIDObject(interp);
540 [ # # ]: 0 : if (idobj == NULL) {
541 : : // XXX Possible GILState issues?
542 : 0 : save_tstate = PyThreadState_Swap(tstate);
543 : 0 : Py_EndInterpreter(tstate);
544 : 0 : PyThreadState_Swap(save_tstate);
545 : 0 : return NULL;
546 : : }
547 : 0 : _PyInterpreterState_RequireIDRef(interp, 1);
548 : 0 : return idobj;
549 : : }
550 : :
551 : : PyDoc_STRVAR(create_doc,
552 : : "create() -> ID\n\
553 : : \n\
554 : : Create a new interpreter and return a unique generated ID.");
555 : :
556 : :
557 : : static PyObject *
558 : 0 : interp_destroy(PyObject *self, PyObject *args, PyObject *kwds)
559 : : {
560 : : static char *kwlist[] = {"id", NULL};
561 : : PyObject *id;
562 : : // XXX Use "L" for id?
563 [ # # ]: 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
564 : : "O:destroy", kwlist, &id)) {
565 : 0 : return NULL;
566 : : }
567 : :
568 : : // Look up the interpreter.
569 : 0 : PyInterpreterState *interp = _PyInterpreterID_LookUp(id);
570 [ # # ]: 0 : if (interp == NULL) {
571 : 0 : return NULL;
572 : : }
573 : :
574 : : // Ensure we don't try to destroy the current interpreter.
575 : 0 : PyInterpreterState *current = _get_current_interp();
576 [ # # ]: 0 : if (current == NULL) {
577 : 0 : return NULL;
578 : : }
579 [ # # ]: 0 : if (interp == current) {
580 : 0 : PyErr_SetString(PyExc_RuntimeError,
581 : : "cannot destroy the current interpreter");
582 : 0 : return NULL;
583 : : }
584 : :
585 : : // Ensure the interpreter isn't running.
586 : : /* XXX We *could* support destroying a running interpreter but
587 : : aren't going to worry about it for now. */
588 [ # # ]: 0 : if (_ensure_not_running(interp) < 0) {
589 : 0 : return NULL;
590 : : }
591 : :
592 : : // Destroy the interpreter.
593 : 0 : PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
594 : : // XXX Possible GILState issues?
595 : 0 : PyThreadState *save_tstate = PyThreadState_Swap(tstate);
596 : 0 : Py_EndInterpreter(tstate);
597 : 0 : PyThreadState_Swap(save_tstate);
598 : :
599 : 0 : Py_RETURN_NONE;
600 : : }
601 : :
602 : : PyDoc_STRVAR(destroy_doc,
603 : : "destroy(id)\n\
604 : : \n\
605 : : Destroy the identified interpreter.\n\
606 : : \n\
607 : : Attempting to destroy the current interpreter results in a RuntimeError.\n\
608 : : So does an unrecognized ID.");
609 : :
610 : :
611 : : static PyObject *
612 : 0 : interp_list_all(PyObject *self, PyObject *Py_UNUSED(ignored))
613 : : {
614 : : PyObject *ids, *id;
615 : : PyInterpreterState *interp;
616 : :
617 : 0 : ids = PyList_New(0);
618 [ # # ]: 0 : if (ids == NULL) {
619 : 0 : return NULL;
620 : : }
621 : :
622 : 0 : interp = PyInterpreterState_Head();
623 [ # # ]: 0 : while (interp != NULL) {
624 : 0 : id = _PyInterpreterState_GetIDObject(interp);
625 [ # # ]: 0 : if (id == NULL) {
626 : 0 : Py_DECREF(ids);
627 : 0 : return NULL;
628 : : }
629 : : // insert at front of list
630 : 0 : int res = PyList_Insert(ids, 0, id);
631 : 0 : Py_DECREF(id);
632 [ # # ]: 0 : if (res < 0) {
633 : 0 : Py_DECREF(ids);
634 : 0 : return NULL;
635 : : }
636 : :
637 : 0 : interp = PyInterpreterState_Next(interp);
638 : : }
639 : :
640 : 0 : return ids;
641 : : }
642 : :
643 : : PyDoc_STRVAR(list_all_doc,
644 : : "list_all() -> [ID]\n\
645 : : \n\
646 : : Return a list containing the ID of every existing interpreter.");
647 : :
648 : :
649 : : static PyObject *
650 : 0 : interp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored))
651 : : {
652 : 0 : PyInterpreterState *interp =_get_current_interp();
653 [ # # ]: 0 : if (interp == NULL) {
654 : 0 : return NULL;
655 : : }
656 : 0 : return _PyInterpreterState_GetIDObject(interp);
657 : : }
658 : :
659 : : PyDoc_STRVAR(get_current_doc,
660 : : "get_current() -> ID\n\
661 : : \n\
662 : : Return the ID of current interpreter.");
663 : :
664 : :
665 : : static PyObject *
666 : 0 : interp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored))
667 : : {
668 : : // Currently, 0 is always the main interpreter.
669 : 0 : int64_t id = 0;
670 : 0 : return _PyInterpreterID_New(id);
671 : : }
672 : :
673 : : PyDoc_STRVAR(get_main_doc,
674 : : "get_main() -> ID\n\
675 : : \n\
676 : : Return the ID of main interpreter.");
677 : :
678 : :
679 : : static PyObject *
680 : 0 : interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
681 : : {
682 : : static char *kwlist[] = {"id", "script", "shared", NULL};
683 : : PyObject *id, *code;
684 : 0 : PyObject *shared = NULL;
685 [ # # ]: 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
686 : : "OU|O:run_string", kwlist,
687 : : &id, &code, &shared)) {
688 : 0 : return NULL;
689 : : }
690 : :
691 : : // Look up the interpreter.
692 : 0 : PyInterpreterState *interp = _PyInterpreterID_LookUp(id);
693 [ # # ]: 0 : if (interp == NULL) {
694 : 0 : return NULL;
695 : : }
696 : :
697 : : // Extract code.
698 : : Py_ssize_t size;
699 : 0 : const char *codestr = PyUnicode_AsUTF8AndSize(code, &size);
700 [ # # ]: 0 : if (codestr == NULL) {
701 : 0 : return NULL;
702 : : }
703 [ # # ]: 0 : if (strlen(codestr) != (size_t)size) {
704 : 0 : PyErr_SetString(PyExc_ValueError,
705 : : "source code string cannot contain null bytes");
706 : 0 : return NULL;
707 : : }
708 : :
709 : : // Run the code in the interpreter.
710 [ # # ]: 0 : if (_run_script_in_interpreter(self, interp, codestr, shared) != 0) {
711 : 0 : return NULL;
712 : : }
713 : 0 : Py_RETURN_NONE;
714 : : }
715 : :
716 : : PyDoc_STRVAR(run_string_doc,
717 : : "run_string(id, script, shared)\n\
718 : : \n\
719 : : Execute the provided string in the identified interpreter.\n\
720 : : \n\
721 : : See PyRun_SimpleStrings.");
722 : :
723 : :
724 : : static PyObject *
725 : 0 : object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds)
726 : : {
727 : : static char *kwlist[] = {"obj", NULL};
728 : : PyObject *obj;
729 [ # # ]: 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
730 : : "O:is_shareable", kwlist, &obj)) {
731 : 0 : return NULL;
732 : : }
733 : :
734 [ # # ]: 0 : if (_PyObject_CheckCrossInterpreterData(obj) == 0) {
735 : 0 : Py_RETURN_TRUE;
736 : : }
737 : 0 : PyErr_Clear();
738 : 0 : Py_RETURN_FALSE;
739 : : }
740 : :
741 : : PyDoc_STRVAR(is_shareable_doc,
742 : : "is_shareable(obj) -> bool\n\
743 : : \n\
744 : : Return True if the object's data may be shared between interpreters and\n\
745 : : False otherwise.");
746 : :
747 : :
748 : : static PyObject *
749 : 0 : interp_is_running(PyObject *self, PyObject *args, PyObject *kwds)
750 : : {
751 : : static char *kwlist[] = {"id", NULL};
752 : : PyObject *id;
753 [ # # ]: 0 : if (!PyArg_ParseTupleAndKeywords(args, kwds,
754 : : "O:is_running", kwlist, &id)) {
755 : 0 : return NULL;
756 : : }
757 : :
758 : 0 : PyInterpreterState *interp = _PyInterpreterID_LookUp(id);
759 [ # # ]: 0 : if (interp == NULL) {
760 : 0 : return NULL;
761 : : }
762 : 0 : int is_running = _is_running(interp);
763 [ # # ]: 0 : if (is_running < 0) {
764 : 0 : return NULL;
765 : : }
766 [ # # ]: 0 : if (is_running) {
767 : 0 : Py_RETURN_TRUE;
768 : : }
769 : 0 : Py_RETURN_FALSE;
770 : : }
771 : :
772 : : PyDoc_STRVAR(is_running_doc,
773 : : "is_running(id) -> bool\n\
774 : : \n\
775 : : Return whether or not the identified interpreter is running.");
776 : :
777 : : static PyMethodDef module_functions[] = {
778 : : {"create", _PyCFunction_CAST(interp_create),
779 : : METH_VARARGS | METH_KEYWORDS, create_doc},
780 : : {"destroy", _PyCFunction_CAST(interp_destroy),
781 : : METH_VARARGS | METH_KEYWORDS, destroy_doc},
782 : : {"list_all", interp_list_all,
783 : : METH_NOARGS, list_all_doc},
784 : : {"get_current", interp_get_current,
785 : : METH_NOARGS, get_current_doc},
786 : : {"get_main", interp_get_main,
787 : : METH_NOARGS, get_main_doc},
788 : :
789 : : {"is_running", _PyCFunction_CAST(interp_is_running),
790 : : METH_VARARGS | METH_KEYWORDS, is_running_doc},
791 : : {"run_string", _PyCFunction_CAST(interp_run_string),
792 : : METH_VARARGS | METH_KEYWORDS, run_string_doc},
793 : :
794 : : {"is_shareable", _PyCFunction_CAST(object_is_shareable),
795 : : METH_VARARGS | METH_KEYWORDS, is_shareable_doc},
796 : :
797 : : {NULL, NULL} /* sentinel */
798 : : };
799 : :
800 : :
801 : : /* initialization function */
802 : :
803 : : PyDoc_STRVAR(module_doc,
804 : : "This module provides primitive operations to manage Python interpreters.\n\
805 : : The 'interpreters' module provides a more convenient interface.");
806 : :
807 : : static int
808 : 1 : module_exec(PyObject *mod)
809 : : {
810 : : /* Add exception types */
811 [ - + ]: 1 : if (exceptions_init(mod) != 0) {
812 : 0 : goto error;
813 : : }
814 : :
815 : : // PyInterpreterID
816 [ - + ]: 1 : if (PyModule_AddType(mod, &_PyInterpreterID_Type) < 0) {
817 : 0 : goto error;
818 : : }
819 : :
820 : 1 : return 0;
821 : :
822 : 0 : error:
823 : 0 : return -1;
824 : : }
825 : :
826 : : static struct PyModuleDef_Slot module_slots[] = {
827 : : {Py_mod_exec, module_exec},
828 : : {0, NULL},
829 : : };
830 : :
831 : : static int
832 : 6 : module_traverse(PyObject *mod, visitproc visit, void *arg)
833 : : {
834 : 6 : module_state *state = get_module_state(mod);
835 : : assert(state != NULL);
836 : 6 : traverse_module_state(state, visit, arg);
837 : 6 : return 0;
838 : : }
839 : :
840 : : static int
841 : 1 : module_clear(PyObject *mod)
842 : : {
843 : 1 : module_state *state = get_module_state(mod);
844 : : assert(state != NULL);
845 : 1 : clear_module_state(state);
846 : 1 : return 0;
847 : : }
848 : :
849 : : static void
850 : 1 : module_free(void *mod)
851 : : {
852 : 1 : module_state *state = get_module_state(mod);
853 : : assert(state != NULL);
854 : 1 : clear_module_state(state);
855 : 1 : }
856 : :
857 : : static struct PyModuleDef moduledef = {
858 : : .m_base = PyModuleDef_HEAD_INIT,
859 : : .m_name = MODULE_NAME,
860 : : .m_doc = module_doc,
861 : : .m_size = sizeof(module_state),
862 : : .m_methods = module_functions,
863 : : .m_slots = module_slots,
864 : : .m_traverse = module_traverse,
865 : : .m_clear = module_clear,
866 : : .m_free = (freefunc)module_free,
867 : : };
868 : :
869 : : PyMODINIT_FUNC
870 : 1 : PyInit__xxsubinterpreters(void)
871 : : {
872 : 1 : return PyModuleDef_Init(&moduledef);
873 : : }
|