Skip to content

Commit 1c7cf14

Browse files
sanchdataegyunkim
authored andcommitted
Update
1 parent ad8f2cb commit 1c7cf14

File tree

3 files changed

+45
-35
lines changed

3 files changed

+45
-35
lines changed

ddtrace/internal/datadog/profiling/stack_v2/include/sampler.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ class Sampler
2525
// Parameters
2626
uint64_t echion_frame_cache_size = g_default_echion_frame_cache_size;
2727

28-
// Helper function; implementation of the echion sampling thread
29-
void sampling_thread(const uint64_t seq_num);
30-
3128
// This is a singleton, so no public constructor
3229
Sampler();
3330

@@ -37,7 +34,7 @@ class Sampler
3734
public:
3835
// Singleton instance
3936
static Sampler& get();
40-
void start();
37+
bool start();
4138
void stop();
4239
void register_thread(uint64_t id, uint64_t native_id, const char* name);
4340
void unregister_thread(uint64_t id);
@@ -46,6 +43,7 @@ class Sampler
4643
PyObject* _asyncio_scheduled_tasks,
4744
PyObject* _asyncio_eager_tasks);
4845
void link_tasks(PyObject* parent, PyObject* child);
46+
void sampling_thread(const uint64_t seq_num);
4947

5048
// The Python side dynamically adjusts the sampling rate based on overhead, so we need to be able to update our
5149
// own intervals accordingly. Rather than a preemptive measure, we assume the rate is ~fairly stable and just

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

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,47 @@
1010

1111
using namespace Datadog;
1212

13-
1413
// Helper class for spawning a std::thread with control over its default stack size
1514
#ifdef __linux__
16-
#include <unistd.h>
1715
#include <sys/resource.h>
18-
template <typename Function, typename... Args>
19-
pthread_t create_thread_with_stack(size_t stack_size, Function&& f, Args&&... args) {
16+
#include <unistd.h>
17+
18+
struct ThreadArgs
19+
{
20+
Sampler* sampler;
21+
uint64_t seq_num;
22+
};
23+
24+
void*
25+
call_sampling_thread(void* args)
26+
{
27+
ThreadArgs* thread_args = static_cast<ThreadArgs*>(args);
28+
Sampler* sampler = thread_args->sampler;
29+
sampler->sampling_thread(thread_args->seq_num);
30+
return nullptr;
31+
}
32+
33+
pthread_t
34+
create_thread_with_stack(size_t stack_size, Sampler* sampler, uint64_t seq_num)
35+
{
2036
pthread_attr_t attr;
21-
pthread_attr_init(&attr);
37+
if (pthread_attr_init(&attr) != 0) {
38+
return 0;
39+
}
2240
if (stack_size > 0) {
2341
pthread_attr_setstacksize(&attr, stack_size);
2442
}
2543

26-
// DAS: I think std::bind here is necessary?
27-
pthread_t thread;
28-
auto* thread_func = new auto(
29-
std::bind(std::forward<Function>(f), std::forward<Args>(args)...)
30-
);
31-
32-
int ret = pthread_create(
33-
&thread,
34-
&attr,
35-
[](void* arg) -> void* {
36-
auto* func = static_cast<decltype(thread_func)>(arg);
37-
(*func)();
38-
delete func;
39-
return nullptr;
40-
},
41-
thread_func
42-
);
44+
pthread_t thread_id;
45+
ThreadArgs thread_args = { sampler, seq_num };
46+
int ret = pthread_create(&thread_id, &attr, call_sampling_thread, &thread_args);
4347

4448
pthread_attr_destroy(&attr);
4549

4650
if (ret != 0) {
47-
delete thread_func;
48-
throw std::runtime_error("Failed to create thread");
51+
return 0;
4952
}
50-
return thread;
53+
return thread_id;
5154
}
5255
#endif
5356

@@ -175,7 +178,7 @@ Sampler::unregister_thread(uint64_t id)
175178
thread_info_map.erase(id);
176179
}
177180

178-
void
181+
bool
179182
Sampler::start()
180183
{
181184
static std::once_flag once;
@@ -188,11 +191,18 @@ Sampler::start()
188191
// We might as well get the default stack size and use that
189192
rlimit stack_sz = {};
190193
getrlimit(RLIMIT_STACK, &stack_sz);
191-
create_thread_with_stack(stack_sz.rlim_cur, &Sampler::sampling_thread, this, ++thread_seq_num); // leak the thread
194+
if (create_thread_with_stack(stack_sz.rlim_cur, this, ++thread_seq_num) == 0) {
195+
return false;
196+
}
192197
#else
193-
std::thread t(&Sampler::sampling_thread, this, ++thread_seq_num);
194-
t.detach();
198+
try {
199+
std::thread t(&Sampler::sampling_thread, this, ++thread_seq_num);
200+
t.detach();
201+
} catch (const std::exception& e) {
202+
return false;
203+
}
195204
#endif
205+
return true;
196206
}
197207

198208
void

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ _stack_v2_start(PyObject* self, PyObject* args, PyObject* kwargs)
2121
}
2222

2323
Sampler::get().set_interval(min_interval_s);
24-
Sampler::get().start();
25-
Py_RETURN_NONE;
24+
if (Sampler::get().start()) {
25+
Py_RETURN_TRUE;
26+
}
27+
Py_RETURN_FALSE;
2628
}
2729

2830
// Bypasses the old-style cast warning with an unchecked helper function

0 commit comments

Comments
 (0)