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

gh-132775: Make _PyXI_session Opaque#134452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 8 additions & 50 deletionsInclude/internal/pycore_crossinterp.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -335,71 +335,29 @@ typedef struct _sharedexception {
PyAPI_FUNC(PyObject *) _PyXI_ApplyError(_PyXI_error *err);


typedef struct xi_session _PyXI_session;
typedef struct _sharedns _PyXI_namespace;

PyAPI_FUNC(void) _PyXI_FreeNamespace(_PyXI_namespace *ns);
PyAPI_FUNC(_PyXI_namespace *) _PyXI_NamespaceFromNames(PyObject *names);
PyAPI_FUNC(int) _PyXI_FillNamespaceFromDict(
_PyXI_namespace *ns,
PyObject *nsobj,
_PyXI_session *session);
PyAPI_FUNC(int) _PyXI_ApplyNamespace(
_PyXI_namespace *ns,
PyObject *nsobj,
PyObject *dflt);


// A cross-interpreter session involves entering an interpreter
//(_PyXI_Enter()), doing some work with it, and finally exiting
// that interpreter(_PyXI_Exit()).
//with_PyXI_Enter(), doing some work with it, and finally exiting
// that interpreterwith_PyXI_Exit().
//
// At the boundaries of the session, both entering and exiting,
// data may be exchanged between the previous interpreter and the
// target one in a thread-safe way that does not violate the
// isolation between interpreters. This includes setting objects
// in the target's __main__ module on the way in, and capturing
// uncaught exceptions on the way out.
struct xi_session {
// Once a session has been entered, this is the tstate that was
// current before the session. If it is different from cur_tstate
// then we must have switched interpreters. Either way, this will
// be the current tstate once we exit the session.
PyThreadState *prev_tstate;
// Once a session has been entered, this is the current tstate.
// It must be current when the session exits.
PyThreadState *init_tstate;
// This is true if init_tstate needs cleanup during exit.
int own_init_tstate;

// This is true if, while entering the session, init_thread took
// "ownership" of the interpreter's __main__ module. This means
// it is the only thread that is allowed to run code there.
// (Caveat: for now, users may still run exec() against the
// __main__ module's dict, though that isn't advisable.)
int running;
// This is a cached reference to the __dict__ of the entered
// interpreter's __main__ module. It is looked up when at the
// beginning of the session as a convenience.
PyObject *main_ns;

// This is set if the interpreter is entered and raised an exception
// that needs to be handled in some special way during exit.
_PyXI_errcode *error_override;
// This is set if exit captured an exception to propagate.
_PyXI_error *error;

// -- pre-allocated memory --
_PyXI_error _error;
_PyXI_errcode _error_override;
};
typedef struct xi_session _PyXI_session;

PyAPI_FUNC(_PyXI_session *) _PyXI_NewSession(void);
PyAPI_FUNC(void) _PyXI_FreeSession(_PyXI_session *);

PyAPI_FUNC(int) _PyXI_Enter(
_PyXI_session *session,
PyInterpreterState *interp,
PyObject *nsupdates);
PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session);

PyAPI_FUNC(PyObject *) _PyXI_GetMainNamespace(_PyXI_session *);

PyAPI_FUNC(PyObject *) _PyXI_ApplyCapturedException(_PyXI_session *session);
PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session);

Expand Down
41 changes: 29 additions & 12 deletionsModules/_interpretersmodule.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -444,42 +444,54 @@ _exec_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
PyObject **p_excinfo)
{
assert(!_PyErr_Occurred(tstate));
_PyXI_session session = {0};
_PyXI_session *session = _PyXI_NewSession();
if (session == NULL) {
return -1;
}

// Prep and switch interpreters.
if (_PyXI_Enter(&session, interp, shareables) < 0) {
if (_PyXI_Enter(session, interp, shareables) < 0) {
if (_PyErr_Occurred(tstate)) {
// If an error occured at this step, it means that interp
// was not prepared and switched.
_PyXI_FreeSession(session);
return -1;
}
// Now, apply the error from another interpreter:
PyObject *excinfo =_PyXI_ApplyError(session.error);
PyObject *excinfo =_PyXI_ApplyCapturedException(session);
if (excinfo != NULL) {
*p_excinfo = excinfo;
}
assert(PyErr_Occurred());
_PyXI_FreeSession(session);
return -1;
}

// Run the script.
int res = _run_script(script, session.main_ns);
int res = -1;
PyObject *mainns = _PyXI_GetMainNamespace(session);
if (mainns == NULL) {
goto finally;
}
res = _run_script(script, mainns);

finally:
// Clean up and switch back.
_PyXI_Exit(&session);
_PyXI_Exit(session);

// Propagate any exception out to the caller.
assert(!PyErr_Occurred());
if (res < 0) {
PyObject *excinfo = _PyXI_ApplyCapturedException(&session);
PyObject *excinfo = _PyXI_ApplyCapturedException(session);
if (excinfo != NULL) {
*p_excinfo = excinfo;
}
}
else {
assert(!_PyXI_HasCapturedException(&session));
assert(!_PyXI_HasCapturedException(session));
}

_PyXI_FreeSession(session);
return res;
}

Expand DownExpand Up@@ -824,22 +836,27 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs)
}
}

_PyXI_session session = {0};
_PyXI_session *session = _PyXI_NewSession();
if (session == NULL) {
return NULL;
}

// Prep and switch interpreters, including apply the updates.
if (_PyXI_Enter(&session, interp, updates) < 0) {
if (_PyXI_Enter(session, interp, updates) < 0) {
if (!PyErr_Occurred()) {
_PyXI_ApplyCapturedException(&session);
_PyXI_ApplyCapturedException(session);
assert(PyErr_Occurred());
}
else {
assert(!_PyXI_HasCapturedException(&session));
assert(!_PyXI_HasCapturedException(session));
}
_PyXI_FreeSession(session);
return NULL;
}

// Clean up and switch back.
_PyXI_Exit(&session);
_PyXI_Exit(session);
_PyXI_FreeSession(session);

Py_RETURN_NONE;
}
Expand Down
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp