Skip to content

Commit ecabc7f

Browse files
authored
Fix #200 Crash related to aligned_alloc and free in context (#208)
* Fix #200 Crash related to aligned_alloc and free in context * If posix_memalign fails, use a sentinel to avoid duplicate calls to posix_memalign
1 parent 9ccd7ba commit ecabc7f

File tree

5 files changed

+46
-11
lines changed

5 files changed

+46
-11
lines changed

ddprof-lib/src/main/cpp/context.cpp

+15-7
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,21 @@ Context &Contexts::get(int tid) {
4747

4848
Context &Contexts::empty() { return DD_EMPTY_CONTEXT; }
4949

50-
void Contexts::initialize(int pageIndex) {
50+
bool Contexts::initialize(int pageIndex) {
5151
if (pageIndex >= _max_pages) {
5252
Counters::increment(CounterId::CONTEXT_BOUNDS_MISS_INITS);
5353
// extreme edge case: pageIndex >= _max_pages if pid_max was increased
5454
// during the process's runtime
55-
return;
55+
return false;
5656
}
5757
if (__atomic_load_n(&_pages[pageIndex], __ATOMIC_ACQUIRE) == NULL) {
5858
u32 capacity = DD_CONTEXT_PAGE_SIZE * sizeof(Context);
59-
Context *page = (Context *)aligned_alloc(sizeof(Context), capacity);
60-
// need to zero the storage because there is no aligned_calloc
59+
Context *page;
60+
if (posix_memalign((void**)&page, sizeof(Context), capacity)) {
61+
Counters::increment(CONTEXT_ALLOC_FAILS);
62+
return false;
63+
}
64+
// need to zero the storage
6165
memset(page, 0, capacity);
6266
if (!__sync_bool_compare_and_swap(&_pages[pageIndex], NULL, page)) {
6367
free(page);
@@ -66,6 +70,7 @@ void Contexts::initialize(int pageIndex) {
6670
Counters::increment(CONTEXT_STORAGE_PAGES);
6771
}
6872
}
73+
return true;
6974
}
7075

7176
void Contexts::reset() {
@@ -78,9 +83,12 @@ void Contexts::reset() {
7883

7984
ContextPage Contexts::getPage(int tid) {
8085
int pageIndex = tid >> DD_CONTEXT_PAGE_SHIFT;
81-
initialize(pageIndex);
82-
return {.capacity = DD_CONTEXT_PAGE_SIZE * sizeof(Context),
83-
.storage = _pages[pageIndex]};
86+
if (initialize(pageIndex)) {
87+
return {.capacity = DD_CONTEXT_PAGE_SIZE * sizeof(Context),
88+
.storage = _pages[pageIndex]};
89+
} else {
90+
return {};
91+
}
8492
}
8593

8694
// The number of pages that can cover all allowed thread IDs

ddprof-lib/src/main/cpp/context.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Contexts {
5252
private:
5353
static int _max_pages;
5454
static Context **_pages;
55-
static void initialize(int pageIndex);
55+
static bool initialize(int pageIndex);
5656

5757
public:
5858
// get must not allocate

ddprof-lib/src/main/cpp/counters.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
X(CONTEXT_BOUNDS_MISS_GETS, "context_bounds_miss_gets") \
4444
X(CONTEXT_CHECKSUM_REJECT_GETS, "context_checksum_reject_gets") \
4545
X(CONTEXT_NULL_PAGE_GETS, "context_null_page_gets") \
46+
X(CONTEXT_ALLOC_FAILS, "context_alloc_fails") \
4647
X(CALLTRACE_STORAGE_BYTES, "calltrace_storage_bytes") \
4748
X(CALLTRACE_STORAGE_TRACES, "calltrace_storage_traces") \
4849
X(LINEAR_ALLOCATOR_BYTES, "linear_allocator_bytes") \

ddprof-lib/src/main/cpp/javaApi.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ Java_com_datadoghq_profiler_JavaProfiler_getContextPage0(JNIEnv *env,
144144
jobject unused,
145145
jint tid) {
146146
ContextPage page = Contexts::getPage((int)tid);
147+
if (page.storage == 0) {
148+
return NULL;
149+
}
147150
return env->NewDirectByteBuffer((void *)page.storage, (jlong)page.capacity);
148151
}
149152

ddprof-lib/src/main/java/com/datadoghq/profiler/JavaProfiler.java

+26-3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static final class TSCFrequencyHolder {
6666

6767
private ByteBuffer[] contextStorage;
6868
private long[] contextBaseOffsets;
69+
private static final ByteBuffer SENTINEL = ByteBuffer.allocate(0);
6970

7071
private JavaProfiler() {
7172
}
@@ -240,6 +241,9 @@ private void setContextJDK8(int tid, long spanId, long rootSpanId) {
240241
return;
241242
}
242243
long pageOffset = getPageUnsafe(tid);
244+
if (pageOffset == 0) {
245+
return;
246+
}
243247
int index = (tid % PAGE_SIZE) * CONTEXT_SIZE;
244248
long base = pageOffset + index;
245249
UNSAFE.putLong(base + SPAN_OFFSET, spanId);
@@ -252,20 +256,27 @@ private void setContextByteBuffer(int tid, long spanId, long rootSpanId) {
252256
return;
253257
}
254258
ByteBuffer page = getPage(tid);
259+
if (page == SENTINEL) {
260+
return;
261+
}
255262
int index = (tid % PAGE_SIZE) * CONTEXT_SIZE;
256263
page.putLong(index + SPAN_OFFSET, spanId);
257264
page.putLong(index + ROOT_SPAN_OFFSET, rootSpanId);
258265
page.putLong(index + CHECKSUM_OFFSET, spanId ^ rootSpanId);
259266
}
260267

261-
262-
263268
private ByteBuffer getPage(int tid) {
264269
int pageIndex = tid / PAGE_SIZE;
265270
ByteBuffer page = contextStorage[pageIndex];
266271
if (page == null) {
267272
// the underlying page allocation is atomic so we don't care which view we have over it
268-
contextStorage[pageIndex] = page = getContextPage0(tid).order(ByteOrder.LITTLE_ENDIAN);
273+
ByteBuffer buffer = getContextPage0(tid);
274+
if (buffer == null) {
275+
page = SENTINEL;
276+
} else {
277+
page = buffer.order(ByteOrder.LITTLE_ENDIAN);
278+
}
279+
contextStorage[pageIndex] = page;
269280
}
270281
return page;
271282
}
@@ -305,6 +316,9 @@ private void setContextJDK8(int tid, int offset, int value) {
305316
return;
306317
}
307318
long pageOffset = getPageUnsafe(tid);
319+
if (pageOffset == 0) {
320+
return;
321+
}
308322
UNSAFE.putInt(pageOffset + addressOf(tid, offset), value);
309323
}
310324

@@ -313,6 +327,9 @@ public void setContextByteBuffer(int tid, int offset, int value) {
313327
return;
314328
}
315329
ByteBuffer page = getPage(tid);
330+
if (page == SENTINEL) {
331+
return;
332+
}
316333
page.putInt(addressOf(tid, offset), value);
317334
}
318335

@@ -330,6 +347,9 @@ void copyTagsJDK8(int tid, int[] snapshot) {
330347
return;
331348
}
332349
long pageOffset = getPageUnsafe(tid);
350+
if (pageOffset == 0) {
351+
return;
352+
}
333353
long address = pageOffset + addressOf(tid, 0);
334354
for (int i = 0; i < snapshot.length; i++) {
335355
snapshot[i] = UNSAFE.getInt(address);
@@ -342,6 +362,9 @@ void copyTagsByteBuffer(int tid, int[] snapshot) {
342362
return;
343363
}
344364
ByteBuffer page = getPage(tid);
365+
if (page == SENTINEL) {
366+
return;
367+
}
345368
int address = addressOf(tid, 0);
346369
for (int i = 0; i < snapshot.length; i++) {
347370
snapshot[i] = page.getInt(address + i * Integer.BYTES);

0 commit comments

Comments
 (0)