Skip to content

Commit fe1cc12

Browse files
committed
fix(event-loop): timers with a complicated job function can't be automatically unref'ed sometimes
See issue: heap-use-after-free in timerJobWrapper (#341) We need to ensure the memory block doesn't move for reallocation before we can use the pointer to the timer's `AsyncHandle`, as we could have multiple new `setTimeout` calls to expand the `_timeoutIdMap` vector while running the job function in parallel.
1 parent 4e20616 commit fe1cc12

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

src/PyEventLoop.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ static PyObject *timerJobWrapper(PyObject *jobFn, PyObject *args) {
3838
PyEventLoop::AsyncHandle::id_t handleId = PyLong_AsLong(PyTuple_GetItem(args, 1));
3939
double delaySeconds = PyFloat_AsDouble(PyTuple_GetItem(args, 2));
4040
bool repeat = (bool)PyLong_AsLong(PyTuple_GetItem(args, 3));
41-
auto handle = PyEventLoop::AsyncHandle::fromId(handleId);
4241

4342
PyObject *ret = PyObject_CallObject(jobFn, NULL); // jobFn()
4443
Py_XDECREF(ret); // don't care about its return value
4544

4645
PyObject *errType, *errValue, *traceback; // we can't call any Python code unless the error indicator is clear
4746
PyErr_Fetch(&errType, &errValue, &traceback);
47+
auto handle = PyEventLoop::AsyncHandle::fromId(handleId); // Making sure a `AsyncHandle::fromId` call is close to its `handle`'s use. We need to ensure the memory block doesn't move for reallocation before we can use the pointer, as we could have multiple new `setTimeout` calls to expand the `_timeoutIdMap` vector while running the job function in parallel.
4848
if (repeat && !handle->cancelled()) {
4949
_enqueueWithDelay(_loop, handleId, jobFn, delaySeconds, repeat);
5050
} else {

0 commit comments

Comments
 (0)