| LIBFEBUG.PY(3) | FreeBSD Library Functions Manual | LIBFEBUG.PY(3) |
febug.SOCKET,
febug.SIGNUM,
febug.ControlledSocket(),
febug.CONTROLLED_SOCKET,
febug.debug_handler(),
febug.Wrapper — User-space
debugfs ABI wrapper library for Python
import febug
febug.SOCKET =
"/var/run/febug.sock"
febug.SIGNUM =
signal.SIGUSR2
"FEBUG_DONT"
in os.environ
os.environ["FEBUG_SOCKET"]
def
febug.ControlledSocket(path
= febug.SOCKET):
socket.socket|None
febug.CONTROLLED_SOCKET =
febug.ControlledSocket()
def
febug.debug_handler(_,
_)
class febug.Wrapper:
of:
Any
def
__init__(self,
of, name,
signal =
febug.SIGNUM)
def
__enter__(self):
febug.Wrapper
def
__exit__(self,
...)
febug.FebugMessage
=
struct.Struct("=QQB4079s")
febug.StopFebugMessage =
struct.Struct("=Q")
febug.AttnFebugMessage =
struct.Struct("=QQ")
Simplifies writing Python programs debuggable with febug(8) by presenting a high-level interface to febug-abi(5).
There are two environment variables that allow a user to customise its behaviour:
FEBUG_DONTFEBUG_SOCKETFEBUG_SOCKET to connect to
febug(8).Unless $FEBUG_DONT, the global
febug.CONTROLLED_SOCKET automatically connects to
febug(8) at
$FEBUG_SOCKET or
febug.SOCKET.
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.CONTROLLED_SOCKET must be in place. It's a no-op
if febug.CONTROLLED_SOCKET is
None.
All objects registered via
febug.Wrapper are formatted as-if via
print(obj),
and all others are rejected. The handler is a no-op if
febug.CONTROLLED_SOCKET is None.
At any time, when the program wishes to
expose a variable, it can construct and operate the
context manager machinery of a
febug.Wrapper, which will send a
febug_message with the specified name and signal
number (defaulting to febug.SIGNUM), and type equal to
0x57726170706572
(Wrapper)
and ID to the address of the Wrapper object. It's a
no-op if febug::CONTROLLED_SOCKET is
None.
When leaving the context
manager context, febug.Wrapper will send a
stop_febug_message. It's a no-op if
febug.CONTROLLED_SOCKET is None.
When it wishes to stop being
debugged, the program may close
febug::CONTROLLED_SOCKET()
and reset it to None.
The following program transforms a list(int) into a list(list(int)) of its factors, but waits a tenth of a second between checks for each factor; the list and the amount of checks can be inspected via a febug(8) mount:
#!/usr/bin/env python3
# SPDX-License-Identifier: 0BSD
import febug, signal, time
signal.signal(febug.SIGNUM, febug.debug_handler)
data = list(range(20))
with febug.Wrapper(0, "tests") as tests:
with febug.Wrapper(data, "cool_data"):
for i in range(len(data)):
fact = []
while data[i] > 1:
for t in range(2, data[i] + 1):
tests.of += 1
time.sleep(0.1)
if data[i] % t == 0:
data[i] //= t
fact.append(t)
data[i] = fact
time.sleep(2)
febug-abi(5) —
the ABI wrapped by this library.
libfebug(3),
libfebug++(3), and
libfebug.rs(3) —
equivalent C, C++, and Rust libraries.
To all who support further development, in particular:
febug mailing list: <~nabijaczleweli/febug@lists.sr.ht>, archived at https://lists.sr.ht/~nabijaczleweli/febug
| May 2, 2025 | febug 1.0.1-1-g9891926af |