fn main()

in src/main.rs [138:228]


fn main() -> Result<()> {
    let _ = Bpftop::parse();

    if !nix::unistd::Uid::current().is_root() {
        return Err(anyhow!("This program must be run as root"));
    }

    // Initialize the journald layer or ignore if not available
    let journald_layer = match tracing_journald::layer() {
        Ok(layer) => Some(layer),
        Err(_) => None,
    };

    // Initialize the tracing subscriber with the journald layer
    let registry = tracing_subscriber::registry()
        .with(journald_layer)
        .with(tracing_subscriber::filter::LevelFilter::INFO);
    // Try to set this subscriber as the global default
    registry.try_init()?;

    let kernel_version = KernelVersion::current()?;
    let _owned_fd: OwnedFd;
    let mut stats_enabled_via_procfs = false;
    let mut iter_link = None;

    info!("Starting bpftop...");
    info!("Kernel: {:?}", kernel_version);

    // enable BPF stats via syscall if kernel version >= 5.8
    if kernel_version >= KernelVersion::new(5, 8, 0) {
        let fd = unsafe { bpf_enable_stats(libbpf_sys::BPF_STATS_RUN_TIME) };
        if fd < 0 {
            return Err(anyhow!("Failed to enable BPF stats via syscall"));
        }
        _owned_fd = unsafe { OwnedFd::from_raw_fd(fd) };
        info!("Enabled BPF stats via syscall");

        // load and attach pid_iter BPF program to get process information
        let skel_builder = PidIterSkelBuilder::default();
        let mut open_object = MaybeUninit::uninit();
        let open_skel = skel_builder.open(&mut open_object)?;
        let mut skel = open_skel.load()?;
        skel.attach()?;
        iter_link = skel.links.bpftop_iter;
    } else {
        // otherwise, enable via procfs
        // but first check if procfs bpf stats were already enabled
        if procfs_bpf_stats_is_enabled()? {
            info!("BPF stats already enabled via procfs");
        } else {
            fs::write(PROCFS_BPF_STATS_ENABLED, b"1").context(format!(
                "Failed to enable BPF stats via {}",
                PROCFS_BPF_STATS_ENABLED
            ))?;
            stats_enabled_via_procfs = true;
            info!("Enabled BPF stats via procfs");
        }
    }

    // capture panic to disable BPF stats via procfs
    let previous_hook = panic::take_hook();
    panic::set_hook(Box::new(move |panic_info| {
        if stats_enabled_via_procfs {
            if let Err(err) = procs_bfs_stats_disable() {
                eprintln!("Failed to disable BPF stats via procfs: {:?}", err);
            }
        }

        previous_hook(panic_info);
    }));

    // setup terminal
    let mut terminal_manager = TerminalManager::new()?;

    // create app and run the draw loop
    let app = App::new();
    app.start_background_thread(iter_link);
    let res = run_draw_loop(&mut terminal_manager.terminal, app);

    // disable BPF stats via procfs if needed
    if stats_enabled_via_procfs {
        procs_bfs_stats_disable()?;
    }

    #[allow(clippy::question_mark)]
    if res.is_err() {
        return res;
    }

    Ok(())
}