bpo-33608: Use _Py_AddPendingCall() in _PyCrossInterpreterData_Releas… · python/cpython@b05b711

@@ -328,28 +328,39 @@ PyInterpreterState_GetID(PyInterpreterState *interp)

328328

}

329329330330331-

PyInterpreterState *

332-

_PyInterpreterState_LookUpID(PY_INT64_T requested_id)

331+

static PyInterpreterState *

332+

interp_look_up_id(PY_INT64_T requested_id)

333333

{

334-

if (requested_id < 0)

335-

goto error;

336-337334

PyInterpreterState *interp = PyInterpreterState_Head();

338335

while (interp != NULL) {

339336

PY_INT64_T id = PyInterpreterState_GetID(interp);

340-

if (id < 0)

337+

if (id < 0) {

341338

return NULL;

342-

if (requested_id == id)

339+

}

340+

if (requested_id == id) {

343341

return interp;

342+

}

344343

interp = PyInterpreterState_Next(interp);

345344

}

346-347-

error:

348-

PyErr_Format(PyExc_RuntimeError,

349-

"unrecognized interpreter ID %lld", requested_id);

350345

return NULL;

351346

}

352347348+

PyInterpreterState *

349+

_PyInterpreterState_LookUpID(PY_INT64_T requested_id)

350+

{

351+

PyInterpreterState *interp = NULL;

352+

if (requested_id >= 0) {

353+

HEAD_UNLOCK();

354+

interp = interp_look_up_id(requested_id);

355+

HEAD_UNLOCK();

356+

}

357+

if (interp == NULL && !PyErr_Occurred()) {

358+

PyErr_Format(PyExc_RuntimeError,

359+

"unrecognized interpreter ID %lld", requested_id);

360+

}

361+

return interp;

362+

}

363+353364354365

int

355366

_PyInterpreterState_IDInitref(PyInterpreterState *interp)

@@ -1280,38 +1291,16 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)

12801291

return 0;

12811292

}

128212931283-

static void

1294+

static int

12841295

_release_xidata(void *arg)

12851296

{

12861297

_PyCrossInterpreterData *data = (_PyCrossInterpreterData *)arg;

12871298

if (data->free != NULL) {

12881299

data->free(data->data);

12891300

}

12901301

Py_XDECREF(data->obj);

1291-

}

1292-1293-

static void

1294-

_call_in_interpreter(PyInterpreterState *interp,

1295-

void (*func)(void *), void *arg)

1296-

{

1297-

/* We would use Py_AddPendingCall() if it weren't specific to the

1298-

* main interpreter (see bpo-33608). In the meantime we take a

1299-

* naive approach.

1300-

*/

1301-

PyThreadState *save_tstate = NULL;

1302-

if (interp != _PyInterpreterState_Get()) {

1303-

// XXX Using the "head" thread isn't strictly correct.

1304-

PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);

1305-

// XXX Possible GILState issues?

1306-

save_tstate = PyThreadState_Swap(tstate);

1307-

}

1308-1309-

func(arg);

1310-1311-

// Switch back.

1312-

if (save_tstate != NULL) {

1313-

PyThreadState_Swap(save_tstate);

1314-

}

1302+

PyMem_Free(data);

1303+

return 0;

13151304

}

1316130513171306

void

@@ -1322,7 +1311,7 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)

13221311

return;

13231312

}

132413131325-

// Switch to the original interpreter.

1314+

// Get the original interpreter.

13261315

PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp);

13271316

if (interp == NULL) {

13281317

// The intepreter was already destroyed.

@@ -1331,10 +1320,24 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)

13311320

}

13321321

return;

13331322

}

1323+

// XXX There's an ever-so-slight race here...

1324+

if (interp->finalizing) {

1325+

// XXX Someone leaked some memory...

1326+

return;

1327+

}

1334132813351329

// "Release" the data and/or the object.

1336-

// XXX Use _Py_AddPendingCall().

1337-

_call_in_interpreter(interp, _release_xidata, data);

1330+

_PyCrossInterpreterData *copied = PyMem_Malloc(sizeof(_PyCrossInterpreterData));

1331+

if (copied == NULL) {

1332+

PyErr_SetString(PyExc_MemoryError,

1333+

"Not enough memory to preserve cross-interpreter data");

1334+

PyErr_Print();

1335+

return;

1336+

}

1337+

memcpy(copied, data, sizeof(_PyCrossInterpreterData));

1338+

if (_Py_AddPendingCall(interp, 0, _release_xidata, copied) != 0) {

1339+

// XXX Queue full or couldn't get lock. Try again somehow?

1340+

}

13381341

}

1339134213401343

PyObject *