Compare commits

...

5 Commits

Author SHA1 Message Date
Andrei Pangin
7f60b4d3ac Release 4.2.1 2025-11-18 17:30:09 +00:00
Andrei Pangin
e5582ad01f Follow up: Workaround for the PERF_EVENT_IOC_REFRESH bug (#1599)
Signed-off-by: Andrei Pangin <1749416+apangin@users.noreply.github.com>
(cherry picked from commit b855e0c2c4)
2025-11-18 17:29:31 +00:00
Andrei Pangin
08866f6616 Workaround for PERF_EVENT_IOC_REFRESH bug (#1599)
(cherry picked from commit 763616aa17)
2025-11-18 15:43:50 +00:00
Andrei Pangin
73622cc19e Do not block any signals during execution of a custom crash handler (#1596)
(cherry picked from commit a25e5194bf)
2025-11-18 15:43:45 +00:00
Andrei Pangin
e7973af2ac Update links to v4.2 in the documentation (#1548)
(cherry picked from commit 538f3a2e48)
2025-11-18 15:43:42 +00:00
11 changed files with 56 additions and 17 deletions

View File

@@ -1,6 +1,13 @@
# Changelog
## [4.2] - Early Access
## [4.2.1] - Maintenance Release
### Bug fixes
- #1599: Workaround for the kernel PERF_EVENT_IOC_REFRESH bug
- #1596: Do not block any signals during execution of a custom crash handler
## [4.2] - 2025-10-20
### Features

View File

@@ -1,4 +1,4 @@
PROFILER_VERSION ?= 4.2
PROFILER_VERSION ?= 4.2.1
ifeq ($(COMMIT_TAG),true)
PROFILER_VERSION := $(PROFILER_VERSION)-$(shell git rev-parse --short=8 HEAD)

View File

@@ -23,12 +23,12 @@ to learn about more features.
# Download
### Stable release: [4.1](https://github.com/async-profiler/async-profiler/releases/tag/v4.1)
### Stable release: [4.2](https://github.com/async-profiler/async-profiler/releases/tag/v4.2)
- Linux x64: [async-profiler-4.1-linux-x64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.1/async-profiler-4.1-linux-x64.tar.gz)
- Linux arm64: [async-profiler-4.1-linux-arm64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.1/async-profiler-4.1-linux-arm64.tar.gz)
- macOS arm64/x64: [async-profiler-4.1-macos.zip](https://github.com/async-profiler/async-profiler/releases/download/v4.1/async-profiler-4.1-macos.zip)
- Profile converters: [jfr-converter.jar](https://github.com/async-profiler/async-profiler/releases/download/v4.1/jfr-converter.jar)
- Linux x64: [async-profiler-4.2-linux-x64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.2/async-profiler-4.2-linux-x64.tar.gz)
- Linux arm64: [async-profiler-4.2-linux-arm64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.2/async-profiler-4.2-linux-arm64.tar.gz)
- macOS arm64/x64: [async-profiler-4.2-macos.zip](https://github.com/async-profiler/async-profiler/releases/download/v4.2/async-profiler-4.2-macos.zip)
- Profile converters: [jfr-converter.jar](https://github.com/async-profiler/async-profiler/releases/download/v4.2/jfr-converter.jar)
### Nightly builds

View File

@@ -2,7 +2,7 @@
async-profiler provides `jfrconv` utility to convert between different profile output formats.
`jfrconv` can be found at the same location as the `asprof` binary. Converter is also available
as a standalone Java application: [`jfr-converter.jar`](https://github.com/async-profiler/async-profiler/releases/download/v4.1/jfr-converter.jar).
as a standalone Java application: [`jfr-converter.jar`](https://github.com/async-profiler/async-profiler/releases/download/v4.2/jfr-converter.jar).
## Supported conversions

View File

@@ -11,7 +11,7 @@ $ java -agentpath:/path/to/libasyncProfiler.so=start,event=cpu,file=profile.html
Agent library is configured through the JVMTI argument interface.
The format of the arguments string is described
[in the source code](https://github.com/async-profiler/async-profiler/blob/v4.1/src/arguments.cpp#L45).
[in the source code](https://github.com/async-profiler/async-profiler/blob/v4.2/src/arguments.cpp#L39).
`asprof` actually converts command line arguments to that format.
Another important use of attaching async-profiler as an agent is for continuous profiling.

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>tools.profiler</groupId>
<artifactId>jfr-converter</artifactId>
<version>4.2</version>
<version>4.2.1</version>
<packaging>jar</packaging>
<name>async-profiler</name>

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>tools.profiler</groupId>
<artifactId>async-profiler</artifactId>
<version>4.2</version>
<version>4.2.1</version>
<packaging>jar</packaging>
<name>async-profiler</name>

View File

@@ -279,8 +279,9 @@ SigAction OS::replaceCrashHandler(SigAction action) {
struct sigaction sa;
sigaction(SIGSEGV, NULL, &sa);
SigAction old_action = sa.sa_handler == SIG_DFL ? restoreSignalHandler : sa.sa_sigaction;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = action;
sa.sa_flags |= SA_SIGINFO | SA_RESTART;
sa.sa_flags |= SA_SIGINFO | SA_RESTART | SA_NODEFER;
sigaction(SIGSEGV, &sa, NULL);
return old_action;
}

View File

@@ -247,14 +247,16 @@ SigAction OS::replaceCrashHandler(SigAction action) {
sigaction(SIGBUS, NULL, &sa);
orig_sigbus_handler = sa.sa_handler == SIG_DFL ? restoreSignalHandler : sa.sa_sigaction;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = action;
sa.sa_flags |= SA_SIGINFO | SA_RESTART;
sa.sa_flags |= SA_SIGINFO | SA_RESTART | SA_NODEFER;
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGSEGV, NULL, &sa);
orig_sigsegv_handler = sa.sa_handler == SIG_DFL ? restoreSignalHandler : sa.sa_sigaction;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = action;
sa.sa_flags |= SA_SIGINFO | SA_RESTART;
sa.sa_flags |= SA_SIGINFO | SA_RESTART| SA_NODEFER;
sigaction(SIGSEGV, &sa, NULL);
// Return an action that dispatches to one of the original handlers depending on signo,

View File

@@ -20,6 +20,7 @@ class PerfEvents : public CpuEngine {
static int _max_events;
static PerfEvent* _events;
static PerfEventType* _event_type;
static int _ioc_enable;
static bool _alluser;
static bool _kernel_stack;
static bool _record_cpu;

View File

@@ -19,6 +19,7 @@
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <linux/perf_event.h>
#include "arch.h"
#include "fdtransferClient.h"
@@ -153,6 +154,17 @@ static void adjustFDLimit() {
}
}
// Workaround for the kernel bug: PERF_EVENT_IOC_REFRESH can hang
// the entire system on Linux 6.16.x and 6.17.x.
// See https://github.com/async-profiler/async-profiler/issues/1578
static bool hasPerfEventRefreshBug() {
static struct utsname u{};
if (u.release[0] == 0 && uname(&u) != 0) {
return false;
}
return strncmp(u.release, "6.16.", 5) == 0 || strncmp(u.release, "6.17.", 5) == 0;
}
struct FunctionWithCounter {
const char* name;
int counter_arg;
@@ -532,6 +544,7 @@ class PerfEvent : public SpinLock {
int PerfEvents::_max_events = 0;
PerfEvent* PerfEvents::_events = NULL;
PerfEventType* PerfEvents::_event_type = NULL;
int PerfEvents::_ioc_enable;
bool PerfEvents::_alluser;
bool PerfEvents::_kernel_stack;
bool PerfEvents::_record_cpu;
@@ -641,7 +654,7 @@ int PerfEvents::createForThread(int tid) {
if (fcntl(fd, F_SETFL, O_ASYNC) < 0 || fcntl(fd, F_SETSIG, _signal) < 0 || fcntl(fd, F_SETOWN_EX, &ex) < 0) {
err = errno;
Log::warn("perf_event fcntl failed: %s", strerror(err));
} else if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) < 0 || ioctl(fd, PERF_EVENT_IOC_REFRESH, 1) < 0) {
} else if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) < 0 || ioctl(fd, _ioc_enable, 1) < 0) {
err = errno;
Log::warn("perf_event ioctl failed: %s", strerror(err));
} else {
@@ -697,6 +710,10 @@ void PerfEvents::signalHandler(int signo, siginfo_t* siginfo, void* ucontext) {
return;
}
if (_ioc_enable == PERF_EVENT_IOC_ENABLE) {
ioctl(siginfo->si_fd, PERF_EVENT_IOC_DISABLE, 0);
}
if (_enabled) {
ExecutionEvent event(TSC::ticks());
u64 counter = readCounter(siginfo, ucontext);
@@ -706,7 +723,7 @@ void PerfEvents::signalHandler(int signo, siginfo_t* siginfo, void* ucontext) {
}
ioctl(siginfo->si_fd, PERF_EVENT_IOC_RESET, 0);
ioctl(siginfo->si_fd, PERF_EVENT_IOC_REFRESH, 1);
ioctl(siginfo->si_fd, _ioc_enable, 1);
}
void PerfEvents::signalHandlerJ9(int signo, siginfo_t* siginfo, void* ucontext) {
@@ -715,6 +732,10 @@ void PerfEvents::signalHandlerJ9(int signo, siginfo_t* siginfo, void* ucontext)
return;
}
if (_ioc_enable == PERF_EVENT_IOC_ENABLE) {
ioctl(siginfo->si_fd, PERF_EVENT_IOC_DISABLE, 0);
}
if (_enabled) {
u64 counter = readCounter(siginfo, ucontext);
J9StackTraceNotification notif;
@@ -726,7 +747,7 @@ void PerfEvents::signalHandlerJ9(int signo, siginfo_t* siginfo, void* ucontext)
}
ioctl(siginfo->si_fd, PERF_EVENT_IOC_RESET, 0);
ioctl(siginfo->si_fd, PERF_EVENT_IOC_REFRESH, 1);
ioctl(siginfo->si_fd, _ioc_enable, 1);
}
const char* PerfEvents::title() {
@@ -830,6 +851,13 @@ Error PerfEvents::start(Arguments& args) {
_alluser = strcmp(args._event, EVENT_CPU) != 0 && !supported();
}
if (strcmp(_event_type->name, "cpu-clock") == 0 && hasPerfEventRefreshBug()) {
Log::debug("Enable workaround for PERF_EVENT_IOC_REFRESH bug");
_ioc_enable = PERF_EVENT_IOC_ENABLE; // opt-in for manual enable/disable
} else {
_ioc_enable = PERF_EVENT_IOC_REFRESH; // autodisable perf_event on counter overflow
}
adjustFDLimit();
int max_events = OS::getMaxThreadId();