LIBFEBUG(3) | Library Functions Manual | LIBFEBUG(3) |
febug_start()
, febug_end()
,
febug_register_type()
,
febug_wrap()
, febug_unwrap()
—
#include
<libfebug.h>
cc
-l
febug
…
#define FEBUG_DONT 0
#define FEBUG_SOCKET "/var/run/febug.sock"
#define FEBUG_SIGNUM SIGUSR2
getenv
("FEBUG_DONT"
);
getenv
("FEBUG_SOCKET"
);
int febug_global_controlled_socket
=
-1;
void febug_start
();
void
febug_start_path
(const
char * path);
void
febug_debug_handler
(int);
void
febug_register_type
(uint64_t
type, void
(*formatter)(int, size_t));
void
febug_wrap
(uint64_t
type, const void *
data, const char *
name, ...);
void
febug_wrap_signal
(uint64_t
type, const void *
data, uint8_t
signal, const char *
name, ...);
void
febug_wrap_signalv
(uint64_t
type, const void *
data, uint8_t
signal, const char *
name, va_list
ap);
void
febug_unwrap
(const
void * data);
void
febug_end
();
There are three compile-time macros that allow customising
libfebug
behaviour:
FEBUG_DONT
FEBUG_SIGNUM
febug_wrap
(). Defaults to
SIGUSR2
.FEBUG_SOCKET
There are two environment variables that allow a user to customise its behaviour:
FEBUG_DONT
FEBUG_SOCKET
FEBUG_SOCKET
to connect to
febug(8).To be debugged, a program needs to, first, call
febug_start_path
() (likely via
febug_start
(), which simply passes
FEBUG_SOCKET
thereto) to
connect to febug(8), which, if
successful, will set febug_global_controlled_socket
appropriately.
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.
The program should register handlers for types of variables it
wishes to handle by calling febug_register_type
()
— those type numbers should be consistent across the program, lest
the wrong handler is called. If no handler was registered for a type,
febug_debug_handler
() will instead return a generic
"not found" message. The handler takes the write end of the pipe
as the first argument, and the variable ID as the second; it shouldn't close
the pipe, as that is done by febug_debug_handler
()
regardless, and the program would then run the risk of closing another file
with the same descriptor simultaneously opened by another thread. 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
call febug_wrap_signalv
() (likely via
febug_wrap_signal
() (likely via
febug_wrap
(), which passes
FEBUG_SIGNUM
thereto)),
which will send a febug_message with the specified type
and signal numbers, ID equal to the data pointer, and name formatted
according to
printf(3).
It's a no-op if febug_global_controlled_socket is
-1.
When the variable goes out of scope, the program should call
febug_unwrap
() to send a
stop_febug_message
with the same data pointer as it
did febug_wrap
(), to prevent reading random data
that might no longer be mapped, or make sense. 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, if any, and deallocate
the type→handler map. 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.
// SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L #include <libfebug.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #define CSTRING_FEBUG_TP 420 static void cstring_febug_formatter(int fd, size_t data) { const char * str = (const char *)data; dprintf(fd, "%s\n", str); } static int char_comp(const void * lhs, const void * rhs) { const struct timespec half_second = {0, 500 * 1000 * 1000}; nanosleep(&half_second, 0); return *(const char *)lhs - *(const char *)rhs; } int main(void) { febug_start(); febug_register_type(CSTRING_FEBUG_TP, cstring_febug_formatter); struct sigaction handler; memset(&handler, 0, sizeof(handler)); handler.sa_handler = febug_debug_handler; if(sigaction(FEBUG_SIGNUM, &handler, 0) == -1) { fprintf(stderr, "sigaction: %s\n", strerror(errno)); return 1; } { __attribute__((__cleanup__(febug_unwrap))) char data[] = "JVLOkgsYmhCyEFxouKzDNajivGlpWqbdBwnfTAXQcreRHPIUSMtZQWERTYUIOPqwertyuiop" "1234567890"; febug_wrap(CSTRING_FEBUG_TP, data, "cool_data"); qsort(data, strlen(data), 1, char_comp); } sleep(2); febug_end(); }
febug mailing list: <~nabijaczleweli/febug@lists.sr.ht>, archived at https://lists.sr.ht/~nabijaczleweli/febug
June 12, 2023 | febug 0.2.1 |