Skip to content

Commit b78a084

Browse files
committed
add on_stack param
Signed-off-by: VGalaxies <[email protected]>
1 parent cae2ae0 commit b78a084

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/profiler.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub struct Profiler {
3535
old_sigaction: Option<signal::SigAction>,
3636
running: bool,
3737

38+
on_stack: bool,
3839
#[cfg(any(
3940
target_arch = "x86_64",
4041
target_arch = "aarch64",
@@ -47,6 +48,7 @@ pub struct Profiler {
4748
#[derive(Clone)]
4849
pub struct ProfilerGuardBuilder {
4950
frequency: c_int,
51+
on_stack: bool,
5052
#[cfg(any(
5153
target_arch = "x86_64",
5254
target_arch = "aarch64",
@@ -60,6 +62,7 @@ impl Default for ProfilerGuardBuilder {
6062
fn default() -> ProfilerGuardBuilder {
6163
ProfilerGuardBuilder {
6264
frequency: 99,
65+
on_stack: false,
6366

6467
#[cfg(any(
6568
target_arch = "x86_64",
@@ -77,6 +80,14 @@ impl ProfilerGuardBuilder {
7780
Self { frequency, ..self }
7881
}
7982

83+
/// Sets whether to use an alternate signal stack.
84+
///
85+
/// This should be enabled when the profiler is used in an environment
86+
/// with small stacks (e.g., inside a Go program) to prevent stack overflow.
87+
pub fn on_stack(self, on_stack: bool) -> Self {
88+
Self { on_stack, ..self }
89+
}
90+
8091
#[cfg(any(
8192
target_arch = "x86_64",
8293
target_arch = "aarch64",
@@ -127,6 +138,7 @@ impl ProfilerGuardBuilder {
127138
Err(Error::CreatingError)
128139
}
129140
Ok(profiler) => {
141+
profiler.on_stack = self.on_stack;
130142
#[cfg(any(
131143
target_arch = "x86_64",
132144
target_arch = "aarch64",
@@ -391,6 +403,7 @@ impl Profiler {
391403
old_sigaction: None,
392404
running: false,
393405

406+
on_stack: false,
394407
#[cfg(any(
395408
target_arch = "x86_64",
396409
target_arch = "aarch64",
@@ -452,16 +465,16 @@ impl Profiler {
452465

453466
fn register_signal_handler(&mut self) -> Result<()> {
454467
let handler = signal::SigHandler::SigAction(perf_signal_handler);
455-
let sigaction = signal::SigAction::new(
456-
handler,
457-
// SA_RESTART will only restart a syscall when it's safe to do so,
458-
// e.g. when it's a blocking read(2) or write(2). See man 7 signal.
468+
// SA_RESTART will only restart a syscall when it's safe to do so,
469+
// e.g. when it's a blocking read(2) or write(2). See man 7 signal.
470+
let mut flags = signal::SaFlags::SA_SIGINFO | signal::SaFlags::SA_RESTART;
471+
if self.on_stack {
459472
// SA_ONSTACK will deliver the signal on an alternate stack. This is crucial
460473
// to prevent a stack overflow if the signal arrives at a thread with
461474
// a small stack, which is common when use pprof-rs in Go runtimes.
462-
signal::SaFlags::SA_SIGINFO | signal::SaFlags::SA_RESTART | signal::SaFlags::SA_ONSTACK,
463-
signal::SigSet::empty(),
464-
);
475+
flags |= signal::SaFlags::SA_ONSTACK;
476+
}
477+
let sigaction = signal::SigAction::new(handler, flags, signal::SigSet::empty());
465478
let old_action = unsafe { signal::sigaction(signal::SIGPROF, &sigaction) }?;
466479
self.old_sigaction = Some(old_action);
467480
Ok(())

0 commit comments

Comments
 (0)