tikv / pprof-rs

A Rust CPU profiler implemented with the help of backtrace-rs
Apache License 2.0
1.3k stars 99 forks source link

missing thread name for main thread #148

Closed viglia closed 2 years ago

viglia commented 2 years ago

Hi,

I'm currently testing pprof-rs in a simple single-threaded application.

In the main function I start the profiler, make some work and then stop the profiler.

Being single-threaded I'd expect the thread_name of the samples to be main but it looks like it was not able to capture the name and it falls back to the threadi_id.

Are there some technical reasons to not use std::thread::current().name instead? link here

YangKeao commented 2 years ago

Are there some technical reasons to not use std::thread::current().name instead? link here

Because running std::thread::current().name will get a thread local variable (behind a RefCell, or not, I cannot remember clearly), which is not safe in a signal handler.

This issue is still valuable, but need more investigation on how to detect the main thread and give it a name.

viglia commented 2 years ago

@YangKeao any update on this?

Also, I forgot to give some important details to help debugging/reproducing the error: I'm having this problem by running the profiler on a Mac M1

viglia commented 2 years ago

I've investigated this myself. I was able to reproduce this problem both on aarch64-Darwin and x86_64-Darwin.

Code to reproduce:

fn main() {
    let current_thread = unsafe { libc::pthread_self() };
    let mut name: [i8; MAX_THREAD_NAME] = [0; MAX_THREAD_NAME];

    let name_ptr = &mut name as *mut [libc::c_char] as *mut libc::c_char;
    let ret = unsafe { libc::pthread_getname_np(current_thread, name_ptr, MAX_THREAD_NAME) };

    let name = unsafe { std::ffi::CStr::from_ptr(name_ptr) };

    println!("ret: {:?}", ret);
    println!("name_ptr: {:?}", name_ptr);
    println!("name: {:?}", name);

    println!("rust thread name: {:?}", std::thread::current().name());

    println!("{}-{}", std::env::consts::ARCH, sys_info::os_type().unwrap());
}

output:

ret: 0
name_ptr: 0x16ba02160
name: ""
rust thread name: Some("main")
aarch64-Darwin

Checking the Rust libc platform specific documentation those two do not seem to be supported yet.

Checking the ci/build.sh I see that those platforms are supported in the nightly build see here.

So, now if I try a nightly build by running:

rustup default nightly

cargo run

I finally get the right output:

ret: 0
name_ptr: 0x16f99e140
name: "main"
rust thread name: Some("main")
aarch64-Darwin

Given this, I guess that there isn't much of a "fix" to be found here. I'd expect it to work properly in some future release of rust but I can't really rely on it as of now.