Skip to content

Commit e35fff9

Browse files
jbachorikclaude
andcommitted
Track and warn when native library limit is exceeded
- Add NATIVE_LIBS_DROPPED counter and LOG_WARN macro - CodeCacheArray::add() returns bool, logs once on overflow - Fix memory leak: delete CodeCache on failed add - Add missing macOS stubs for sigaction protection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2fcf604 commit e35fff9

8 files changed

Lines changed: 48 additions & 10 deletions

File tree

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef _CODECACHE_H
77
#define _CODECACHE_H
88

9+
#include "common.h"
10+
#include "counters.h"
911
#include "utils.h"
1012

1113
#include <jvmti.h>
@@ -258,9 +260,10 @@ class CodeCacheArray {
258260
volatile int _reserved; // next slot to reserve (CAS by writers)
259261
volatile int _count; // published count (all indices < _count have non-NULL pointers)
260262
volatile size_t _used_memory;
263+
bool _overflow_reported;
261264

262265
public:
263-
CodeCacheArray() : _reserved(0), _count(0), _used_memory(0) {
266+
CodeCacheArray() : _reserved(0), _count(0), _used_memory(0), _overflow_reported(false) {
264267
memset(_libs, 0, MAX_NATIVE_LIBS * sizeof(CodeCache *));
265268
}
266269

@@ -272,10 +275,17 @@ class CodeCacheArray {
272275
// Pointer-first add: reserve a slot via CAS on _reserved, store the
273276
// pointer with RELEASE, then advance _count. Readers see count() grow
274277
// only after the pointer is visible, so indices < count() never yield NULL.
275-
void add(CodeCache *lib) {
278+
bool add(CodeCache *lib) {
276279
int slot = __atomic_load_n(&_reserved, __ATOMIC_RELAXED);
277280
do {
278-
if (slot >= MAX_NATIVE_LIBS) return;
281+
if (slot >= MAX_NATIVE_LIBS) {
282+
Counters::increment(NATIVE_LIBS_DROPPED);
283+
if (!_overflow_reported) {
284+
_overflow_reported = true;
285+
LOG_WARN("Native library limit reached (%d). Additional libraries will not be tracked.", MAX_NATIVE_LIBS);
286+
}
287+
return false;
288+
}
279289
} while (!__atomic_compare_exchange_n(&_reserved, &slot, slot + 1,
280290
true, __ATOMIC_RELAXED, __ATOMIC_RELAXED));
281291
assert(__atomic_load_n(&_libs[slot], __ATOMIC_RELAXED) == nullptr);
@@ -289,6 +299,7 @@ class CodeCacheArray {
289299
// wait for preceding slots to publish
290300
}
291301
__atomic_store_n(&_count, slot + 1, __ATOMIC_RELEASE);
302+
return true;
292303
}
293304

294305
CodeCache* at(int index) const {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define _COMMON_H
33

44
#include <cstddef>
5+
#include <cstdio>
56

67
// Knuth's multiplicative constant (golden ratio * 2^64 for 64-bit)
78
// Used for hash distribution in various components
@@ -16,4 +17,10 @@ constexpr size_t KNUTH_MULTIPLICATIVE_CONSTANT = 0x9e3779b97f4a7c15ULL;
1617
#define TEST_LOG(fmt, ...) // No-op in non-debug mode
1718
#endif
1819

20+
// Lightweight stderr warning that does not depend on the Log subsystem.
21+
// Safe to call from low-level code where Log may not be initialized.
22+
#define LOG_WARN(fmt, ...) do { \
23+
fprintf(stderr, "[ddprof] [WARN] " fmt "\n", ##__VA_ARGS__); \
24+
} while (0)
25+
1926
#endif // _COMMON_H

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
X(WALKVM_FP_CHAIN_ATTEMPT, "walkvm_fp_chain_attempt") \
9494
X(WALKVM_FP_CHAIN_REACHED_CODEHEAP, "walkvm_fp_chain_reached_codeheap") \
9595
X(WALKVM_ANCHOR_NOT_IN_JAVA, "walkvm_anchor_not_in_java") \
96+
X(NATIVE_LIBS_DROPPED, "native_libs_dropped") \
9697
X(SIGACTION_PATCHED_LIBS, "sigaction_patched_libs") \
9798
X(SIGACTION_INTERCEPTED, "sigaction_intercepted")
9899
#define X_ENUM(a, b) a,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class LibraryPatcher {
4646
static void initialize() { }
4747
static void patch_libraries() { }
4848
static void unpatch_libraries() { }
49+
static void patch_sigaction() { }
4950
};
5051

5152
#endif

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,4 +484,16 @@ SigAction OS::replaceSigsegvHandler(SigAction action) {
484484
return old_action;
485485
}
486486

487+
// No GOT-based sigaction interception on macOS — these are no-ops.
488+
void OS::protectSignalHandlers(SigAction segvHandler, SigAction busHandler) {
489+
}
490+
491+
SigAction OS::getSegvChainTarget() {
492+
return nullptr;
493+
}
494+
495+
SigAction OS::getBusChainTarget() {
496+
return nullptr;
497+
}
498+
487499
#endif // __APPLE__

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,9 +1202,9 @@ Engine *Profiler::selectCpuEngine(Arguments &args) {
12021202
if (VM::isOpenJ9()) {
12031203
if (!J9Ext::shouldUseAsgct() || !J9Ext::can_use_ASGCT()) {
12041204
if (!J9Ext::is_jvmti_jmethodid_safe()) {
1205-
fprintf(stderr, "[ddprof] [WARN] Safe jmethodID access is not available on this JVM. Using "
1205+
LOG_WARN("Safe jmethodID access is not available on this JVM. Using "
12061206
"CPU profiler on your own risk. Use -XX:+KeepJNIIDs=true JVM "
1207-
"flag to make access to jmethodIDs safe, if your JVM supports it\n");
1207+
"flag to make access to jmethodIDs safe, if your JVM supports it");
12081208
}
12091209
TEST_LOG("J9[cpu]=jvmti");
12101210
return &j9_engine;
@@ -1234,9 +1234,9 @@ Engine *Profiler::selectWallEngine(Arguments &args) {
12341234
if (VM::isOpenJ9()) {
12351235
if (args._wallclock_sampler == JVMTI || !J9Ext::shouldUseAsgct() || !J9Ext::can_use_ASGCT()) {
12361236
if (!J9Ext::is_jvmti_jmethodid_safe()) {
1237-
fprintf(stderr, "[ddprof] [WARN] Safe jmethodID access is not available on this JVM. Using "
1237+
LOG_WARN("Safe jmethodID access is not available on this JVM. Using "
12381238
"wallclock profiler on your own risk. Use -XX:+KeepJNIIDs=true JVM "
1239-
"flag to make access to jmethodIDs safe, if your JVM supports it\n");
1239+
"flag to make access to jmethodIDs safe, if your JVM supports it");
12401240
}
12411241
j9_engine.sampleIdleThreads();
12421242
TEST_LOG("J9[wall]=jvmti");

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,9 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
957957

958958
if (haveKernelSymbols()) {
959959
cc->sort();
960-
array->add(cc);
960+
if (!array->add(cc)) {
961+
delete cc;
962+
}
961963
} else {
962964
delete cc;
963965
}
@@ -995,7 +997,9 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
995997

996998
cc->sort();
997999
applyPatch(cc);
998-
array->add(cc);
1000+
if (!array->add(cc)) {
1001+
delete cc;
1002+
}
9991003
}
10001004

10011005
if (array->count() >= MAX_NATIVE_LIBS && !_libs_limit_reported) {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) {
213213
Log::warn("Could not parse symbols from %s", path);
214214
}
215215
cc->sort();
216-
array->add(cc);
216+
if (!array->add(cc)) {
217+
delete cc;
218+
}
217219
} else {
218220
delete cc;
219221
}

0 commit comments

Comments
 (0)