Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4a4ac3a

Browse files
gh-132775: Make _PyXI_session Opaque (gh-134452)
This is mostly a refactor to clean things up a bit, most notably the "XI namespace" code.Making the session opaque requires adding the following internal-only functions:* _PyXI_NewSession()* _PyXI_FreeSession()* _PyXI_GetMainNamespace()
1 parentec736e7 commit4a4ac3a

File tree

3 files changed

+456
-366
lines changed

3 files changed

+456
-366
lines changed

‎Include/internal/pycore_crossinterp.h

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -335,71 +335,29 @@ typedef struct _sharedexception {
335335
PyAPI_FUNC(PyObject*)_PyXI_ApplyError(_PyXI_error*err);
336336

337337

338-
typedefstructxi_session_PyXI_session;
339-
typedefstruct_sharedns_PyXI_namespace;
340-
341-
PyAPI_FUNC(void)_PyXI_FreeNamespace(_PyXI_namespace*ns);
342-
PyAPI_FUNC(_PyXI_namespace*)_PyXI_NamespaceFromNames(PyObject*names);
343-
PyAPI_FUNC(int)_PyXI_FillNamespaceFromDict(
344-
_PyXI_namespace*ns,
345-
PyObject*nsobj,
346-
_PyXI_session*session);
347-
PyAPI_FUNC(int)_PyXI_ApplyNamespace(
348-
_PyXI_namespace*ns,
349-
PyObject*nsobj,
350-
PyObject*dflt);
351-
352-
353338
// A cross-interpreter session involves entering an interpreter
354-
//(_PyXI_Enter()), doing some work with it, and finally exiting
355-
// that interpreter(_PyXI_Exit()).
339+
//with_PyXI_Enter(), doing some work with it, and finally exiting
340+
// that interpreterwith_PyXI_Exit().
356341
//
357342
// At the boundaries of the session, both entering and exiting,
358343
// data may be exchanged between the previous interpreter and the
359344
// target one in a thread-safe way that does not violate the
360345
// isolation between interpreters. This includes setting objects
361346
// in the target's __main__ module on the way in, and capturing
362347
// uncaught exceptions on the way out.
363-
structxi_session {
364-
// Once a session has been entered, this is the tstate that was
365-
// current before the session. If it is different from cur_tstate
366-
// then we must have switched interpreters. Either way, this will
367-
// be the current tstate once we exit the session.
368-
PyThreadState*prev_tstate;
369-
// Once a session has been entered, this is the current tstate.
370-
// It must be current when the session exits.
371-
PyThreadState*init_tstate;
372-
// This is true if init_tstate needs cleanup during exit.
373-
intown_init_tstate;
374-
375-
// This is true if, while entering the session, init_thread took
376-
// "ownership" of the interpreter's __main__ module. This means
377-
// it is the only thread that is allowed to run code there.
378-
// (Caveat: for now, users may still run exec() against the
379-
// __main__ module's dict, though that isn't advisable.)
380-
intrunning;
381-
// This is a cached reference to the __dict__ of the entered
382-
// interpreter's __main__ module. It is looked up when at the
383-
// beginning of the session as a convenience.
384-
PyObject*main_ns;
385-
386-
// This is set if the interpreter is entered and raised an exception
387-
// that needs to be handled in some special way during exit.
388-
_PyXI_errcode*error_override;
389-
// This is set if exit captured an exception to propagate.
390-
_PyXI_error*error;
391-
392-
// -- pre-allocated memory --
393-
_PyXI_error_error;
394-
_PyXI_errcode_error_override;
395-
};
348+
typedefstructxi_session_PyXI_session;
349+
350+
PyAPI_FUNC(_PyXI_session*)_PyXI_NewSession(void);
351+
PyAPI_FUNC(void)_PyXI_FreeSession(_PyXI_session*);
396352

397353
PyAPI_FUNC(int)_PyXI_Enter(
398354
_PyXI_session*session,
399355
PyInterpreterState*interp,
400356
PyObject*nsupdates);
401357
PyAPI_FUNC(void)_PyXI_Exit(_PyXI_session*session);
402358

359+
PyAPI_FUNC(PyObject*)_PyXI_GetMainNamespace(_PyXI_session*);
360+
403361
PyAPI_FUNC(PyObject*)_PyXI_ApplyCapturedException(_PyXI_session*session);
404362
PyAPI_FUNC(int)_PyXI_HasCapturedException(_PyXI_session*session);
405363

‎Modules/_interpretersmodule.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -444,42 +444,54 @@ _exec_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
444444
PyObject**p_excinfo)
445445
{
446446
assert(!_PyErr_Occurred(tstate));
447-
_PyXI_sessionsession= {0};
447+
_PyXI_session*session=_PyXI_NewSession();
448+
if (session==NULL) {
449+
return-1;
450+
}
448451

449452
// Prep and switch interpreters.
450-
if (_PyXI_Enter(&session,interp,shareables)<0) {
453+
if (_PyXI_Enter(session,interp,shareables)<0) {
451454
if (_PyErr_Occurred(tstate)) {
452455
// If an error occured at this step, it means that interp
453456
// was not prepared and switched.
457+
_PyXI_FreeSession(session);
454458
return-1;
455459
}
456460
// Now, apply the error from another interpreter:
457-
PyObject*excinfo=_PyXI_ApplyError(session.error);
461+
PyObject*excinfo=_PyXI_ApplyCapturedException(session);
458462
if (excinfo!=NULL) {
459463
*p_excinfo=excinfo;
460464
}
461465
assert(PyErr_Occurred());
466+
_PyXI_FreeSession(session);
462467
return-1;
463468
}
464469

465470
// Run the script.
466-
intres=_run_script(script,session.main_ns);
471+
intres=-1;
472+
PyObject*mainns=_PyXI_GetMainNamespace(session);
473+
if (mainns==NULL) {
474+
gotofinally;
475+
}
476+
res=_run_script(script,mainns);
467477

478+
finally:
468479
// Clean up and switch back.
469-
_PyXI_Exit(&session);
480+
_PyXI_Exit(session);
470481

471482
// Propagate any exception out to the caller.
472483
assert(!PyErr_Occurred());
473484
if (res<0) {
474-
PyObject*excinfo=_PyXI_ApplyCapturedException(&session);
485+
PyObject*excinfo=_PyXI_ApplyCapturedException(session);
475486
if (excinfo!=NULL) {
476487
*p_excinfo=excinfo;
477488
}
478489
}
479490
else {
480-
assert(!_PyXI_HasCapturedException(&session));
491+
assert(!_PyXI_HasCapturedException(session));
481492
}
482493

494+
_PyXI_FreeSession(session);
483495
returnres;
484496
}
485497

@@ -824,22 +836,27 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs)
824836
}
825837
}
826838

827-
_PyXI_sessionsession= {0};
839+
_PyXI_session*session=_PyXI_NewSession();
840+
if (session==NULL) {
841+
returnNULL;
842+
}
828843

829844
// Prep and switch interpreters, including apply the updates.
830-
if (_PyXI_Enter(&session,interp,updates)<0) {
845+
if (_PyXI_Enter(session,interp,updates)<0) {
831846
if (!PyErr_Occurred()) {
832-
_PyXI_ApplyCapturedException(&session);
847+
_PyXI_ApplyCapturedException(session);
833848
assert(PyErr_Occurred());
834849
}
835850
else {
836-
assert(!_PyXI_HasCapturedException(&session));
851+
assert(!_PyXI_HasCapturedException(session));
837852
}
853+
_PyXI_FreeSession(session);
838854
returnNULL;
839855
}
840856

841857
// Clean up and switch back.
842-
_PyXI_Exit(&session);
858+
_PyXI_Exit(session);
859+
_PyXI_FreeSession(session);
843860

844861
Py_RETURN_NONE;
845862
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp