Skip to content

Commit 54a3a0e

Browse files
authored
fix(profiling): release the GIL for internal mutation (#14852)
## Description We make the stack v2 sampler release the GIL when performing internal state mutation that can require acquiring other internal locks. This gives the chance to other threads to make progress while the tracking operations wait on an internal mutex.
1 parent 5a3d6bd commit 54a3a0e

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

ddtrace/internal/datadog/profiling/stack_v2/src/stack_v2.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ stack_v2_thread_register(PyObject* self, PyObject* args)
7373
return NULL;
7474
}
7575

76+
Py_BEGIN_ALLOW_THREADS;
7677
Sampler::get().register_thread(id, native_id, name);
78+
Py_END_ALLOW_THREADS;
79+
7780
Py_RETURN_NONE;
7881
}
7982

@@ -87,8 +90,11 @@ stack_v2_thread_unregister(PyObject* self, PyObject* args)
8790
return NULL;
8891
}
8992

93+
Py_BEGIN_ALLOW_THREADS;
9094
Sampler::get().unregister_thread(id);
9195
ThreadSpanLinks::get_instance().unlink_span(id);
96+
Py_END_ALLOW_THREADS;
97+
9298
Py_RETURN_NONE;
9399
}
94100

@@ -122,7 +128,9 @@ _stack_v2_link_span(PyObject* self, PyObject* args, PyObject* kwargs)
122128
span_type = empty_string.c_str();
123129
}
124130

131+
Py_BEGIN_ALLOW_THREADS;
125132
ThreadSpanLinks::get_instance().link_span(thread_id, span_id, local_root_span_id, std::string(span_type));
133+
Py_END_ALLOW_THREADS;
126134

127135
Py_RETURN_NONE;
128136
}
@@ -140,7 +148,9 @@ stack_v2_track_asyncio_loop(PyObject* self, PyObject* args)
140148
return NULL;
141149
}
142150

151+
Py_BEGIN_ALLOW_THREADS;
143152
Sampler::get().track_asyncio_loop(thread_id, loop);
153+
Py_END_ALLOW_THREADS;
144154

145155
Py_RETURN_NONE;
146156
}
@@ -172,7 +182,9 @@ stack_v2_link_tasks(PyObject* self, PyObject* args)
172182
return NULL;
173183
}
174184

185+
Py_BEGIN_ALLOW_THREADS;
175186
Sampler::get().link_tasks(parent, child);
187+
Py_END_ALLOW_THREADS;
176188

177189
Py_RETURN_NONE;
178190
}
@@ -211,7 +223,9 @@ track_greenlet(PyObject* Py_UNUSED(m), PyObject* args)
211223
return NULL;
212224
}
213225

226+
Py_BEGIN_ALLOW_THREADS;
214227
Sampler::get().track_greenlet(greenlet_id, greenlet_name, frame);
228+
Py_END_ALLOW_THREADS;
215229

216230
Py_RETURN_NONE;
217231
}
@@ -223,7 +237,9 @@ untrack_greenlet(PyObject* Py_UNUSED(m), PyObject* args)
223237
if (!PyArg_ParseTuple(args, "l", &greenlet_id))
224238
return NULL;
225239

240+
Py_BEGIN_ALLOW_THREADS;
226241
Sampler::get().untrack_greenlet(greenlet_id);
242+
Py_END_ALLOW_THREADS;
227243

228244
Py_RETURN_NONE;
229245
}
@@ -236,7 +252,9 @@ link_greenlets(PyObject* Py_UNUSED(m), PyObject* args)
236252
if (!PyArg_ParseTuple(args, "ll", &child, &parent))
237253
return NULL;
238254

255+
Py_BEGIN_ALLOW_THREADS;
239256
Sampler::get().link_greenlets(parent, child);
257+
Py_END_ALLOW_THREADS;
240258

241259
Py_RETURN_NONE;
242260
}
@@ -250,7 +268,9 @@ update_greenlet_frame(PyObject* Py_UNUSED(m), PyObject* args)
250268
if (!PyArg_ParseTuple(args, "lO", &greenlet_id, &frame))
251269
return NULL;
252270

271+
Py_BEGIN_ALLOW_THREADS;
253272
Sampler::get().update_greenlet_frame(greenlet_id, frame);
273+
Py_END_ALLOW_THREADS;
254274

255275
Py_RETURN_NONE;
256276
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
Profiling: prevent potential deadlocks with thread pools.

0 commit comments

Comments
 (0)