.\" Automatically generated from an mdoc input file. Do not edit. .\"" SPDX-License-Identifier: MIT .TH "LIBFEBUG.RS" "3" "January 20, 2021" "OpenBSD 6.8" "Library Functions Manual" .nh .if n .ad l .SH "NAME" \fBfebug::start\fR, \fBfebug::Wrapper\fR, \fBfebug::Wrappable\fR, \fBfebug::StaticWrappable\fR, \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR, \fIfebug::FORMATTERS\fR \- User-space debugfs ABI wrapper library for Rust .SH "SYNOPSIS" .nf .RS 0n [dependencies] febug = "0.1.0" .RE .fi .PP \fBgetenv("FEBUG_DONT")\fR .br \fBgetenv("FEBUG_SOCKET")\fR .PP \fIstatic GLOBAL_CONTROLLED_SOCKET: AtomicI32\fR = -1; .HP 4n \fBfn febug::start\fR(); .HP 4n \fBfn febug::start_raw\fR(\fIpath:\ &[u8]\fR); .HP 4n \fBextern 'C' fn debug_handler\fR(\fI_:\ c_int\fR); .HP 4n \fBbool fn febug::install_handler\fR(); .HP 4n \fBbool fn febug::install_handler_signal\fR(\fIsignal:\ u8\fR); .HP 4n \fBfn febug::end\fR(); .PP \fIstatic febug::FORMATTERS: Lazy>>\fR .PP \fBtrait febug::StaticWrappable: 'static;\fR .br .PD 0 .HP 4n \fBWrapper fn febug::StaticWrappable::wrap\fR(\fI&self\fR, \fIname:\ Arguments<'_>\fR); .PD .HP 4n \fBWrapper fn febug::StaticWrappable::wrap_signal\fR(\fI&self\fR, \fIsignal:\ u8\fR, \fIname:\ Arguments<'_>\fR); .PP \fBtrait febug::Wrappable;\fR .br .PD 0 .HP 4n \fBWrapper fn febug::Wrappable::wrap\fR(\fI&self\fR, \fItp:\ u64\fR, \fIname:\ Arguments<'_>\fR); .PD .HP 4n \fBWrapper fn febug::Wrappable::wrap_signal\fR(\fI&self\fR, \fItp:\ u64\fR, \fIsignal:\ u8\fR, \fIname:\ Arguments<'_>\fR); .PP \fBstruct febug::Wrapper\fR { /* \[u2026] */ }; .br .PD 0 .HP 4n \fBWrapper fn febug::Wrapper::new\fR(\fI&self\fR, \fItp:\ u64\fR, \fIdata:argument\fR, \fIname:\ fmt::Arguments\fR, \fIname:\ Arguments<'_>\fR); .PD .HP 4n \fBWrapper fn febug::Wrapper::new_signal\fR(\fI&self\fR, \fItp:\ u64\fR, \fIdata:argument\fR, \fIsignal:\ u8\fR, \fIname:\ fmt::Arguments\fR, \fIname:\ Arguments<'_>\fR); .PP \fBstruct febug::abi::FebugMessage;\fR \fBstruct febug::abi::StopFebugMessage;\fR \fBstruct febug::abi::AttnFebugMessage;\fR .SH "DESCRIPTION" \fBlibfebug.rs\fR allows a programmer to simplify writing Rust programs debuggable with febug(8) by presenting a high-level interface to febug-abi(5). .PP There are three compile-time environment variables that allow a programmer to customise its behaviour: .TP 8n \fBFEBUG_DONT\fR .br If set, all functions turn into no-ops; this is intended as a way to easily disable febug(8) integration completely on release builds. .TP 8n \fBFEBUG_SIGNUM\fR .br The signal to request from febug(8) when using \fBfebug_wrap\fR(). Defaults to \fRSIGUSR2\fR. .TP 8n \fBFEBUG_SOCKET\fR .br The path to connect to febug(8) on. Defaults to \fI/var/run/febug.sock\fR. .PP There are two environment variables that allow a user to customise its behaviour: .TP 8n \fIFEBUG_DONT\fR If set, don't try to connect to febug(8), so all library functions become no-ops. .TP 8n \fIFEBUG_SOCKET\fR If set, use its value instead of \fBFEBUG_SOCKET\fR to connect to febug(8) .PP To be debugged, a program needs to, first, call \fBfebug::start_raw\fR() (likely via \fBfebug::start\fR(), which simply passes \fIb\&"/var/run/febug.sock"\fR thereto) to connect to febug(8), which, if successful, will set \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR to the connection's file descriptor. .PP The program needs to install \fBfebug::debug_handler\fR() (or a wrapper around it) as the signal handler for \fBFEBUG_SIGNUM\fR (and any other signals, if different ones are explicitly requested; if \fRSIGKILL\fR, some event loop that answers on \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR must be in place). It's a no-op if \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR is -1. This finishes set-up. A convenience \fBfebug::install_handler\fR() function is provided, doing just that, and returning \fBtrue\fR if the handler was installed. .PP The program should register handlers for types of variables it wishes to handle by adding entries to \fIfebug::FORMATTERS\fR. If no handler was registered for a type, or the lock was poisoned, \fBfebug::debug_handler\fR() will write a generic "not found" message. The key is \fBstd::any::TypeId\fR corresponding to the debugged type; if your type is not not \fB'static\fR, 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 \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR is -1. .PP At any time, when the program wishes to expose a variable, it can construct \fBfebug::Wrapper\fR (likely via one of the convenience \fBfebug::StaticWrappable\fR or \fBfebug::Wrappable\fR traits), which will send a \fBfebug_message\fR with the specified type and signal numbers (defaulting to \fRSIGUSR2 ),\fR ID equal to the address of the data argument, and name formatted. It's a no-op if \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR is -1. .PP When dropped, \fBfebug::Wrapper\fR will send a \fBstop_febug_message\fR. It's a no-op if \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR is -1. .PP When it wishes to stop being debugged, the program may call \fBfebug::end\fR() which will shutter and reset \fIfebug::GLOBAL_CONTROLLED_SOCKET\fR, The program may omit this if it'd be the last thing it did before exiting, since the kernel will close all FDs and free all mappings anyway. .SH "EXAMPLES" 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: .nf .sp .RS 6n // 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::(), |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::>(); for t in threads { let _ = t.join(); } } .RE .fi .SH "SEE ALSO" febug-abi(5) \[u2014] the ABI wrapped by this library. .PP libfebug(3) \[u2014] an equivalent C library. .PP libfebug++(3) \[u2014] an equivalent C++ library. .SH "AUTHORS" Written by \[u043D]\[u0430]\[u0431] <\fInabijaczleweli@nabijaczleweli.xyz\fR> .SH "SPECIAL THANKS" To all who support further development, in particular: .PD 0 .TP 8n \fB\(bu\fR ThePhD .TP 8n \fB\(bu\fR Embark Studios .PD .SH "REPORTING BUGS" \fIfebug tracker\fR: \fBhttps://todo.sr.ht/~nabijaczleweli/febug\fR .PP febug mailing list: <\fI~nabijaczleweli/febug@lists.sr.ht\fR> archived at \fBhttps://lists.sr.ht/~nabijaczleweli/febug\fR