LIBFEBUG.PY(3) | 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 =
"/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_DONT
FEBUG_SOCKET
FEBUG_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
September 2, 2024 | febug 1.0.0-2-g9ab5a53e |