Skip to content

bpo-32604: Fix memory leaks in the new _xxsubinterpreters module. #5507

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Clean up memory ops for _sharedexception.
  • Loading branch information
ericsnowcurrently committed Feb 3, 2018
commit 0c0fa3df7cc1f003fefabd4f620857f4b93c986b
129 changes: 103 additions & 26 deletions Modules/_xxsubinterpretersmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,48 +193,91 @@ _sharedns_apply(_sharedns *shared, PyObject *ns)
// of the exception in the calling interpreter.

typedef struct _sharedexception {
char *name;
char *msg;
} _sharedexception;

static _sharedexception *
_sharedexception_new(void)
{
_sharedexception *err = PyMem_NEW(_sharedexception, 1);
if (err == NULL) {
PyErr_NoMemory();
return NULL;
}
err->name = NULL;
err->msg = NULL;
return err;
}

static void
_sharedexception_free(_sharedexception *exc)
_sharedexception_clear(_sharedexception *exc)
{
if (exc->name != NULL) {
PyMem_Free(exc->name);
}
if (exc->msg != NULL) {
PyMem_Free(exc->msg);
}
}

static void
_sharedexception_free(_sharedexception *exc)
{
_sharedexception_clear(exc);
PyMem_Free(exc);
}

static _sharedexception *
_get_shared_exception(void)
_sharedexception_bind(PyObject *exctype, PyObject *exc, PyObject *tb)
{
_sharedexception *err = PyMem_NEW(_sharedexception, 1);
assert(exctype != NULL);
char *failure = NULL;

_sharedexception *err = _sharedexception_new();
if (err == NULL) {
return NULL;
goto finally;
}
PyObject *exc;
PyObject *value;
PyObject *tb;
PyErr_Fetch(&exc, &value, &tb);
PyObject *msg;
if (value == NULL) {
msg = PyUnicode_FromFormat("%S", exc);

PyObject *name = PyUnicode_FromFormat("%S", exctype);
if (name == NULL) {
failure = "unable to format exception type name";
goto finally;
}
else {
msg = PyUnicode_FromFormat("%S: %S", exc, value);
err->name = _copy_raw_string(name);
if (err->name == NULL) {
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
failure = "out of memory copying exception type name";
}
failure = "unable to encode and copy exception type name";
goto finally;
}
if (msg == NULL) {
err->msg = "unable to format exception";
return err;

if (exc != NULL) {
PyObject *msg = PyUnicode_FromFormat("%S", exc);
if (msg == NULL) {
failure = "unable to format exception message";
goto finally;
}
err->msg = _copy_raw_string(msg);
Py_DECREF(msg);
if (err->msg == NULL) {
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
failure = "out of memory copying exception message";
}
failure = "unable to encode and copy exception message";
goto finally;
}
}

err->msg = _copy_raw_string(msg);
Py_DECREF(msg);
if (err->msg == NULL) {
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
err->msg = "MemoryError: out of memory copying error message";
finally:
if (failure != NULL) {
PyErr_Clear();
if (err->name != NULL) {
PyMem_Free(err->name);
err->name = NULL;
}
err->msg = "unable to encode and copy exception message";
err->msg = failure;
}
return err;
}
Expand All @@ -260,9 +303,22 @@ interp_exceptions_init(PyObject *ns)
}

static void
_apply_shared_exception(_sharedexception *exc)
_sharedexception_apply(_sharedexception *exc)
{
PyErr_SetString(RunFailedError, exc->msg);
if (exc->name != NULL) {
if (exc->msg != NULL) {
PyErr_Format(RunFailedError, "%s: %s", exc->name, exc->msg);
}
else {
PyErr_SetString(RunFailedError, exc->name);
}
}
else if (exc->msg != NULL) {
PyErr_SetString(RunFailedError, exc->msg);
}
else {
PyErr_SetNone(RunFailedError);
}
}

/* channel-specific code */
Expand Down Expand Up @@ -1475,6 +1531,10 @@ static int
_run_script(PyInterpreterState *interp, const char *codestr,
_sharedns *shared, _sharedexception **exc)
{
PyObject *exctype = NULL;
PyObject *excval = NULL;
PyObject *tb = NULL;

PyObject *main_mod = PyMapping_GetItemString(interp->modules, "__main__");
if (main_mod == NULL) {
goto error;
Expand Down Expand Up @@ -1504,10 +1564,27 @@ _run_script(PyInterpreterState *interp, const char *codestr,
Py_DECREF(result); // We throw away the result.
}

*exc = NULL;
return 0;
error:
*exc = _get_shared_exception();
PyErr_Fetch(&exctype, &excval, &tb);
Py_INCREF(exctype);
Py_XINCREF(excval);
Py_XINCREF(tb);
PyErr_Clear();

_sharedexception *sharedexc = _sharedexception_bind(exctype, excval, tb);
Py_DECREF(exctype);
Py_XDECREF(excval);
Py_XDECREF(tb);
if (sharedexc == NULL) {
fprintf(stderr, "RunFailedError: script raised an uncaught exception");
PyErr_Clear();
}
else {
assert(!PyErr_Occurred());
*exc = sharedexc;
}
return -1;
}

Expand Down Expand Up @@ -1539,7 +1616,7 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr,

// Propagate any exception out to the caller.
if (exc != NULL) {
_apply_shared_exception(exc);
_sharedexception_apply(exc);
_sharedexception_free(exc);
}
else if (result != 0) {
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy