Skip to content

Commit

Permalink
Assign distinct thread IDs to greenlets
Browse files Browse the repository at this point in the history
Greenlets aren't threads, but they are distinct threads of execution
within a single process, with distinct stacks. Reflect this by
generating distinct thread IDs for them.

Signed-off-by: Matt Wozniski <mwozniski@bloomberg.net>
  • Loading branch information
godlygeek authored and pablogsal committed Oct 28, 2022
1 parent fcf6c65 commit bf3e99d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/memray/_memray/tracking_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ PythonStackTracker::installGreenletTraceFunctionIfNeeded()
}

void
PythonStackTracker::handleGreenletSwitch(PyObject*, PyObject*)
PythonStackTracker::handleGreenletSwitch(PyObject* from, PyObject* to)
{
RecursionGuard guard;

Expand All @@ -388,6 +388,25 @@ PythonStackTracker::handleGreenletSwitch(PyObject*, PyObject*)
emitPendingPushesAndPops();
}

// Save current TID on old greenlet. Print errors but otherwise ignore them.
PyObject* tid = PyLong_FromUnsignedLong(t_tid);
if (!tid || 0 != PyObject_SetAttrString(from, "_memray_tid", tid)) {
PyErr_Print();
}
Py_XDECREF(tid);

// Restore TID from new greenlet, or generate a new one. Ignore errors:
// maybe we haven't seen this TID before, or maybe someone overwrote our
// attribute, but either way we can recover by generating a new one.
tid = PyObject_GetAttrString(to, "_memray_tid");
if (!tid || !PyLong_CheckExact(tid)) {
PyErr_Clear();
t_tid = generate_next_tid();
} else {
t_tid = PyLong_AsUnsignedLong(tid);
}
Py_XDECREF(tid);

// Re-create our TLS stack from our Python frames, most recent last.
// Note: `frame` may be null; the new greenlet may not have a Python stack.
PyFrameObject* frame = PyEval_GetFrame();
Expand Down
5 changes: 5 additions & 0 deletions tests/integration/test_greenlet.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,8 @@ def stack(alloc):

assert stack(vallocs[6]) == ["valloc", "test", "<module>"]
assert vallocs[6].size == 70 * 1024

# 0 and 2 are fruit, 1 and 3 and 4 and 5 are animal, 6 is main.
assert vallocs[0].tid != vallocs[1].tid != vallocs[6].tid
assert vallocs[0].tid == vallocs[2].tid
assert vallocs[1].tid == vallocs[3].tid == vallocs[4].tid == vallocs[5].tid

0 comments on commit bf3e99d

Please sign in to comment.