LIBFEBUG.RS(3) Library Functions Manual LIBFEBUG.RS(3)

febug::start(), febug::Wrapper, febug::Wrappable, febug::StaticWrappable, febug::GLOBAL_CONTROLLED_SOCKET, febug::FORMATTERS
User-space debugfs ABI wrapper library for Rust

[dependencies]
febug = "0.2.1"


env!("FEBUG_DONT")?
env!("FEBUG_SOCKET") = "/var/run/febug.sock"
env!("FEBUG_SIGNUM") = SIGUSR2

env::var("FEBUG_DONT");
env::var("FEBUG_SOCKET");


static GLOBAL_CONTROLLED_SOCKET:
AtomicI32 = -1
;


fn febug::start();

fn febug::start_raw(path: &[u8]);

extern "C" fn debug_handler(_: c_int);

bool fn febug::install_handler();

bool fn febug::install_handler_signal(signal: u8);

fn febug::end();

static febug::FORMATTERS:
Lazy<Mutex<BTreeMap<TypeId, fn(&mut File, usize)>>>
;


trait febug::StaticWrappable: 'static;

Wrapper<Self> fn febug::StaticWrappable::wrap(&self, name: Arguments<'_>);

Wrapper<Self> fn febug::StaticWrappable::wrap_signal(&self, signal: u8, name: Arguments<'_>);


trait febug::Wrappable;

Wrapper<Self> fn febug::Wrappable::wrap(&self, tp: u64, name: Arguments<'_>);

Wrapper<Self> fn febug::Wrappable::wrap_signal(&self, tp: u64, signal: u8, name: Arguments<'_>);


struct febug::Wrapper<T> { /* … */ };

Wrapper<T> fn febug::Wrapper::new(&self, tp: u64, data:argument, name: fmt::Arguments, name: Arguments<'_>);

Wrapper<T> fn febug::Wrapper::new_signal(&self, tp: u64, data:argument, signal: u8, name: fmt::Arguments, name: Arguments<'_>);


struct febug::abi::FebugMessage;
struct febug::abi::StopFebugMessage;
struct febug::abi::AttnFebugMessage;

Simplifies writing Rust programs debuggable with febug(8) by presenting a high-level interface to febug-abi(5).

There are three compile-time environment variables that allow customising libfebug.rs behaviour:

If set, all functions turn into no-ops; this is intended as a way to easily disable febug(8) integration completely on release builds.
The signal to request from febug(8) when using febug_wrap(). Defaults to SIGUSR2.
The path to connect to febug(8) on. Defaults to /var/run/febug.sock.

There are two environment variables that allow a user to customise its behaviour:

If set, don't try to connect to febug(8), so all library functions become no-ops.
If set, use its value instead of the built-in FEBUG_SOCKET to connect to febug(8).

To be debugged, a program needs to, first, call febug::start_raw() (likely via febug::start(), which simply passes b"/var/run/febug.sock" thereto) to connect to febug(8), which, if successful, will set febug::GLOBAL_CONTROLLED_SOCKET to the connection's file descriptor.

The program needs to install febug::debug_handler() (or a wrapper around it) as the signal handler for FEBUG_SIGNUM (and any other signals, if different ones are explicitly requested); if notifications are disabled (by requesting SIGKILL), some event loop that answers on febug::GLOBAL_CONTROLLED_SOCKET must be in place. It's a no-op if febug::GLOBAL_CONTROLLED_SOCKET is -1. A convenience febug::install_handler() function is provided, doing just that, and returning true if the handler was installed.

The program should register handlers for types of variables it wishes to handle by adding entries to febug::FORMATTERS. If no handler was registered for a type, or the lock was poisoned, febug::debug_handler() will write a generic "not found" message. The key is std::any::TypeId corresponding to the debugged type; if your type is not 'static, lie here. The handler takes the write end of the pipe as the first argument, and the variable ID as the second. It's a no-op if febug::GLOBAL_CONTROLLED_SOCKET is -1.

At any time, when the program wishes to expose a variable, it can construct a febug::Wrapper (likely via one of the convenience febug::StaticWrappable or febug::Wrappable traits), which will send a febug_message with the specified type and signal numbers (defaulting to SIGUSR2), ID equal to the address of the data argument, and name formatted. It's a no-op if febug::GLOBAL_CONTROLLED_SOCKET is -1.

When dropped, febug::Wrapper will send a stop_febug_message. It's a no-op if febug::GLOBAL_CONTROLLED_SOCKET is -1.

When it wishes to stop being debugged, the program may call febug::end() which will shut and reset febug::GLOBAL_CONTROLLED_SOCKET. The program may omit this if it'd be the last thing it did before exiting, since the kernel will close all file descriptors and free all mappings anyway.

The following program spawns 10 threads, each successive one sorting a longer subsection of a String, but waits a quarter-second between each comparison; the String for each thread and the amount of comparisons can be inspected via a febug(8) mount:
// SPDX-License-Identifier: MIT


extern crate febug;

use febug::StaticWrappable;
use std::time::Duration;
use std::any::TypeId;
use std::io::Write;
use std::thread;


fn main() {
    febug::start();
    if febug::install_handler() {
        febug::FORMATTERS.lock()
            .unwrap()
            .insert(TypeId::of::<String>(), |of, vid| {
                let data = unsafe { &*(vid as *const String) };

                let _ = of.write_all(data.as_bytes());
                let _ = of.write_all(b"\n");
            });
    }


    let threads = (0..10)
        .map(|i| {
            thread::spawn(move || {
                let mut sorteing = "The quick red fox jumps over the lazy brown \
                                    dog... tHE QUICK RED FOX JUMPS OVER THE \
                                    LAZY BROWN DOG!!"
                                       [0..(i + 1) * 10]
                    .to_string();
                let _sorteing_w = sorteing.wrap(format_args!("cool_data_{}", i));

                unsafe { sorteing.as_bytes_mut() }.sort_unstable_by(|a, b| {
                    thread::sleep(Duration::from_millis(250));
                    a.cmp(b)
                });

                thread::sleep(Duration::from_secs(2));
            })
        })
        .collect::<Vec<_>>();
    for t in threads {
        let _ = t.join();
    }
}

febug-abi(5) — the ABI wrapped by this library.
libfebug(3) and libfebug++(3) — equivalent C and C++ libraries.

To all who support further development, in particular:

febug tracker

febug mailing list: <~nabijaczleweli/febug@lists.sr.ht>, archived at https://lists.sr.ht/~nabijaczleweli/febug

June 12, 2023 febug 0.2.1