~nabijaczleweli/febug

ddb1572762dc945610a56c829780f9c598601ff8 — наб autouploader 6 months ago d2d1324
Debian manpage update by job 451321
M Debian/febug-abi.5 => Debian/febug-abi.5 +1 -1
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "FEBUG-ABI" "5" "January 31, 2021" "Debian" "File Formats Manual"
.TH "FEBUG-ABI" "5" "March 7, 2021" "Debian" "File Formats Manual"
.nh
.if n .ad l
.SH "NAME"

M Debian/febug-abi.5.html => Debian/febug-abi.5.html +94 -104
@@ 314,136 314,124 @@ html {		--bg: #1E1F21;
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">struct febug_message</code>,
  <code class="Nm">struct stop_febug_message</code>,
  <code class="Nm">struct attn_febug_message</code> &#x2014;
<code class="Nm">struct febug_message</code>, <code class="Nm">struct
  stop_febug_message</code>, <code class="Nm">struct attn_febug_message</code>
  &#x2014;
<div class="Nd">User-space debugfs ABI</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<code class="In">#include
  &lt;<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/febug-abi.h">febug-abi.h</a>&gt;</code>
<div class="Pp"></div>
<b class="Sy">struct febug_message;</b>
<div class="Pp"></div>
<b class="Sy">struct stop_febug_message;</b>
<div class="Pp"></div>
<b class="Sy">struct attn_febug_message;</b>
<p class="Pp"><b class="Sy">struct febug_message;</b></p>
<p class="Pp"><b class="Sy">struct stop_febug_message;</b></p>
<p class="Pp"><b class="Sy">struct attn_febug_message;</b></p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The febug ABI consists of two messages sent from the program wishing to be
  debugged to <a class="Xr" href="febug.8.html">febug(8)</a>, and one sent from
  <a class="Xr" href="febug.8.html">febug(8)</a> to the program.
<div class="Pp"></div>
To be debugged, the program must create a socket with
  <code class="Li">socket(AF_UNIX, SOCK_SEQPACKET, 0)</code> and
  <a class="Xr">connect(2)</a> to the appropriate end-point
  (<span class="Pa">/run/febug.sock</span>, conventionally). Sending
  the first message will pass along client credentials; sending the null message
  is a valid way to trigger this. After <a class="Xr" href="febug.8.html">febug(8)</a>
  receives credentials, a directory corresponding to the debugged process' PID
  will be created in the filesystem.
<div class="Pp"></div>
<i class="Em">All</i> messages must be sent in a single
  <a class="Xr">send(2)</a> or
  <a class="Xr">sendmsg(2)</a> call, specifying the exact size of the
  message, as that's what's used to differentiate between different messages.
  <a class="Xr" href="febug.8.html">febug(8)</a> will ignore messages (whose sizes) it
  does not recognise.
<div class="Pp"></div>
Afterward, for each variable of interest, the process should send a 4096-byte
  <b class="Sy">febug_message</b>, defined as follows:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
struct [[packed]] febug_message { 
    uint64_t variable_id; 
    uint64_t variable_type; 
    uint8_t signal; 
    char name[/* Enough to bring the overall size to 4096. */]; 
<p class="Pp">To be debugged, the program must create a socket with
    <code class="Li">socket(AF_UNIX, SOCK_SEQPACKET, 0)</code> and
    <a class="Xr">connect(2)</a> to the appropriate end-point
    (<span class="Pa">/run/febug.sock</span>, conventionally). Sending the first
    message will pass along client credentials; sending the null message is a
    valid way to trigger this. After <a class="Xr" href="febug.8.html">febug(8)</a> receives
    credentials, a directory corresponding to the debugged process' PID will be
    created in the filesystem.</p>
<p class="Pp"><i class="Em">All</i> messages must be sent in a single
    <a class="Xr">send(2)</a> or <a class="Xr">sendmsg(2)</a> call, specifying
    the exact size of the message, as that's what's used to differentiate
    between different messages. <a class="Xr" href="febug.8.html">febug(8)</a> will ignore messages
    (whose sizes) it does not recognise.</p>
<p class="Pp">Afterward, for each variable of interest, the process should send
    a 4096-byte <b class="Sy">febug_message</b>, defined as follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct [[packed]] febug_message {
    uint64_t variable_id;
    uint64_t variable_type;
    uint8_t signal;
    char name[/* Enough to bring the overall size to 4096. */];
};
</pre>
</div>
<div class="Pp"></div>
Wherein:
<p class="Pp">Wherein:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><i class="Em">variable_id</i> is the locally unique identifier
      of the variable (e.g. a pointer to that variable).</dd>
  <dd><i class="Em">variable_id</i> is the locally unique identifier of the
      variable (e.g. a pointer to that variable).</dd>
  <dt></dt>
  <dd><i class="Em">variable_type</i> is the moral equivalent of
      <var class="Vt">void *</var>
      <var class="Va">userdata</var> &#x2014; it is simply passed
      back to the program, unchanged (e.g. a function pointer to a
    formatter).</dd>
      <var class="Vt">void *</var> <var class="Va">userdata</var> &#x2014; it is
      simply passed back to the program, unchanged (e.g. a function pointer to a
      formatter).</dd>
  <dt></dt>
  <dd><i class="Em">signal</i> is the signal to send to the program
      when a variable is to be read (see below).
      <i class="Em">name</i> is the globally unique name of this
      variable &#x2014; a NUL terminator is respected, if it occurs before the
      end of the array, but is not required if the name truly spans to the final
      byte. If the name is the same as one of an already-present variable, it
      will be overridden.</dd>
  <dd><i class="Em">signal</i> is the signal to send to the program when a
      variable is to be read (see below). <i class="Em">name</i> is the globally
      unique name of this variable &#x2014; a NUL terminator is respected, if it
      occurs before the end of the array, but is not required if the name truly
      spans to the final byte. If the name is the same as one of an
      already-present variable, it will be overridden.</dd>
</dl>
<div class="Pp"></div>
When <a class="Xr" href="febug.8.html">febug(8)</a> receives
  <b class="Sy">febug_message</b>, it creates a file under the
  process' directory. When that file is opened,
  <a class="Xr" href="febug.8.html">febug(8)</a> will:
<p class="Pp">When <a class="Xr" href="febug.8.html">febug(8)</a> receives
    <b class="Sy">febug_message</b>, it creates a file under the process'
    directory. When that file is opened, <a class="Xr" href="febug.8.html">febug(8)</a> will:</p>
<ol class="Bl-enum">
  <li>send the process an <b class="Sy">attn_febug_message</b> with a
      single file descriptor via <code class="Dv">SCM_RIGHTS</code>
      auxilliary data (confer <a class="Xr">cmsg(3)</a>) representing
      the write end of a pipe &#x2014; subsequent reads are serviced directly by
      the opposing end.</li>
  <li>send the process an <b class="Sy">attn_febug_message</b> with a single
      file descriptor via <code class="Dv">SCM_RIGHTS</code> auxilliary data
      (confer <a class="Xr">cmsg(3)</a>) representing the write end of a pipe
      &#x2014; subsequent reads are serviced directly by the opposing end.</li>
  <li><a class="Xr">kill(2)</a> the process with the signal from the
      <var class="Va">signal</var> field if it wasn't
      <code class="Dv">SIGKILL</code>.</li>
</ol>
<div class="Pp"></div>
Note, that the sent file descriptor <i class="Em">must</i> be closed
  by the program when it's done serialising the variable, and therefore, if the
  process opts not to receive a signal, it <i class="Em">must</i>
  handle the message through some other mechanism.
<div class="Pp"></div>
<b class="Sy">attn_febug_message</b> is 16 bytes, and defined as
  follows:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
struct [[packed]] attn_febug_message { 
    uint64_t variable_id; 
    uint64_t variable_type; 
<p class="Pp">Note, that the sent file descriptor <i class="Em">must</i> be
    closed by the program when it's done serialising the variable, and
    therefore, if the process opts not to receive a signal, it
    <i class="Em">must</i> handle the message through some other mechanism.</p>
<p class="Pp"><b class="Sy">attn_febug_message</b> is 16 bytes, and defined as
    follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct [[packed]] attn_febug_message {
    uint64_t variable_id;
    uint64_t variable_type;
};
</pre>
</div>
<div class="Pp"></div>
Both fields correspond to the ones sent in the
  <b class="Sy">febug_message</b> that installed the variable.
<div class="Pp"></div>
The process may receive any amount of
  <b class="Sy">attn_febug_message</b> until it sends an 8-byte
  <b class="Sy">stop_febug_message</b>, defined as follows:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
struct [[packed]] stop_febug_message { 
    uint64_t variable_id; 
<p class="Pp">Both fields correspond to the ones sent in the
    <b class="Sy">febug_message</b> that installed the variable.</p>
<p class="Pp">The process may receive any amount of
    <b class="Sy">attn_febug_message</b> until it sends an 8-byte
    <b class="Sy">stop_febug_message</b>, defined as follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct [[packed]] stop_febug_message {
    uint64_t variable_id;
};
</pre>
</div>
<div class="Pp"></div>
Upon receipt, the corresponding variable, if any, is removed from the
  filesystem.
<div class="Pp"></div>
When the process' end of the socket is closed, all extant variables are freed,
  and the process' directory is removed.
<p class="Pp">Upon receipt, the corresponding variable, if any, is removed from
    the filesystem.</p>
<p class="Pp">When the process' end of the socket is closed, all extant
    variables are freed, and the process' directory is removed.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> and
  <a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; libraries that wrap this
  ABI.
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> and <a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014;
  libraries that wrap this ABI.
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:


@@ 451,18 439,20 @@ To all who support further development, in particular:
  <li>ThePhD</li>
  <li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
  BUGS</a></h1>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
  tracker</a>
<div class="Pp"></div>
febug mailing list:
  &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
  archived at
  <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></div>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<p class="Pp">febug mailing list:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    archived at
    <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">January 31, 2021</td>
    <td class="foot-date">March 7, 2021</td>
    <td class="foot-os">Debian</td>
  </tr>
</table>

M Debian/febug.8 => Debian/febug.8 +6 -0
@@ 32,6 32,12 @@ and
\fB\-V\fR \fBor\fR \fB\--version\fR
are self-explanatory.
.PP
\fB\-d\fR
enables debug output from both
\fBfebug\fR
and
\fBlibfuse\fR.
.PP
\fBfebug\fR
passes all arguments (which have to, therefore, include
\fImountpoint\fR)

M Debian/febug.8.html => Debian/febug.8.html +79 -64
@@ 314,90 314,103 @@ html {		--bg: #1E1F21;
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug</code> &#x2014;
<div class="Nd">User-space debugfs filesystem driver</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<table class="Nm">
  <tr>
    <td><code class="Nm">febug</code></td>
    <td>[<div class="Op"><code class="Fl">-hV</code></div>]
      [<div class="Op"><b class="Sy">libfuse options</b></div>]
    <td>[<code class="Fl">-hV</code>] [<b class="Sy">libfuse options</b>]
      <var class="Ar">mountpoint</var></td>
  </tr>
</table>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<code class="Nm">febug</code> mounts a filesystem at
  <var class="Ar">mountpoint</var> that allows programs to register
  themselves and expose variables to be (relatively) non-intrusively inspected
  at run-time, inspired by the
  <var class="Ar">mountpoint</var> that allows programs to register themselves
  and expose variables to be (relatively) non-intrusively inspected at run-time,
  inspired by the
  <a class="Lk" href="https://www.kernel.org/doc/html/latest/filesystems/debugfs.html">debugfs</a>
  filesystem.
<div class="Pp"></div>
See <a class="Xr">febug-abi(8)</a> for implementation details. And
  the <a class="Sx" href="#EXAMPLES">EXAMPLES</a> section for an
  example debug session.
<p class="Pp">See <a class="Xr">febug-abi(8)</a> for implementation details. And
    the <a class="Sx" href="#EXAMPLES">EXAMPLES</a> section for an example debug
    session.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="OPTIONS"><a class="permalink" href="#OPTIONS">OPTIONS</a></h1>
<code class="Fl">-h</code> <code class="Nm">or</code>
  <code class="Fl">--help</code> and
  <code class="Fl">-V</code> <code class="Nm">or</code>
  <code class="Fl">--version</code> are self-explanatory.
<div class="Pp"></div>
<code class="Nm">febug</code> passes all arguments (which have to,
  therefore, include <var class="Ar">mountpoint</var>) to
  <a class="Xr">fuse_main(3)</a>, with
  <code class="Fl">-f</code> (foreground) and
  <code class="Fl">-o</code>
  <code class="Nm">default_permissions</code> appended. If run with
  effective UID of 0, it also appends <code class="Fl">-o</code>
  <code class="Nm">allow_other</code>.
  <code class="Fl">--help</code> and <code class="Fl">-V</code>
  <code class="Nm">or</code> <code class="Fl">--version</code> are
  self-explanatory.
<p class="Pp"><code class="Fl">-d</code> enables debug output from both
    <code class="Nm">febug</code> and <code class="Nm">libfuse</code>.</p>
<p class="Pp"><code class="Nm">febug</code> passes all arguments (which have to,
    therefore, include <var class="Ar">mountpoint</var>) to
    <a class="Xr">fuse_main(3)</a>, with <code class="Fl">-f</code> (foreground)
    and <code class="Fl">-o</code> <code class="Nm">default_permissions</code>
    appended. If run with effective UID of 0, it also appends
    <code class="Fl">-o</code> <code class="Nm">allow_other</code>.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="ENVIRONMENT"><a class="permalink" href="#ENVIRONMENT">ENVIRONMENT</a></h1>
<i class="Em">FEBUG_SOCKET</i> the socket at which to listen for
  programs, or <span class="Pa">/run/febug.sock</span> by default.
<i class="Em">FEBUG_SOCKET</i> the socket at which to listen for programs, or
  <span class="Pa">/run/febug.sock</span> by default.
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
<div class="Bd Bd-indent">
<pre class="Li">
# systemctl start febug 
$ findmnt /run/febug 
/run/febug febug fuse.febug rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other 
$ ./out/examples/vector-sort &amp; 
[1] 1409 
$ LD_LIBRARY_PATH=out ./out/examples/string-qsort &amp; 
[2] 1410 
$ ls /run/febug/ 
1409 1410 
$ ls -l /run/febug/ 
dr-xr-x--- 4 nabijaczleweli users 0 Jan 15 19:52 1409 
dr-xr-x--- 3 nabijaczleweli users 0 Jan 15 19:52 1410 
$ ls /run/febug/1409/ 
comparisons cool_data 
$ cat /run/febug/1409/* 
24 
-3 -2 -3 -2 -3 -2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3 
$ cat /run/febug/1409/* 
45 
-3 -2 -3 -2 -3 -2 -3 -2 -2 -3 -3 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3 
$ grep . /run/febug/*/* 
/run/febug/1409/comparisons:71 
/run/febug/1409/cool_data:-3 -3 -3 -3 -3 -3 -2 -2 -2 -2 -2 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3 
/run/febug/1410/cool_data:3012987654ACEFOLJKODNIEMIGHBPPbdWwnfTpXQcreRlVvUSitZQWjRTYUazuqwertyuiopoxyhmYsgkq 
$ kill %1 
$ ls /run/febug/ 
<pre>
# systemctl start febug
$ findmnt /run/febug
/run/febug febug fuse.febug rw,nosuid,nodev,relatime,user_id=0,group_id=0,default_permissions,allow_other
$ ./out/examples/vector-sort &amp;
[1] 1409
$ LD_LIBRARY_PATH=out ./out/examples/string-qsort &amp;
[2] 1410
$ ls /run/febug/
1409 1410
$ ls -l /run/febug/
dr-xr-x--- 4 nabijaczleweli users 0 Jan 15 19:52 1409
dr-xr-x--- 3 nabijaczleweli users 0 Jan 15 19:52 1410
$ ls /run/febug/1409/
comparisons cool_data
$ cat /run/febug/1409/*
24
-3 -2 -3 -2 -3 -2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 -2 -3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
$ cat /run/febug/1409/*
45
-3 -2 -3 -2 -3 -2 -3 -2 -2 -3 -3 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
$ grep . /run/febug/*/*
/run/febug/1409/comparisons:71
/run/febug/1409/cool_data:-3 -3 -3 -3 -3 -3 -2 -2 -2 -2 -2 -2 -1 3 -1 1 0 0 1 2 3 2 -1 3 0 1 2 3 -1 2 1 0 1 2 3 -1 0 -1 0 1 2 3
/run/febug/1410/cool_data:3012987654ACEFOLJKODNIEMIGHBPPbdWwnfTpXQcreRlVvUSitZQWjRTYUazuqwertyuiopoxyhmYsgkq
$ kill %1
$ ls /run/febug/
1410
</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI used to connect with
  this filesystem.
<div class="Pp"></div>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; a library wrapping this ABI.
<div class="Pp"></div>
<a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; a C++ library wrapping this
  ABI.
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI used to connect with this
  filesystem.
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; a library wrapping this
    ABI.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; a C++ library wrapping
    this ABI.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:


@@ 405,15 418,17 @@ To all who support further development, in particular:
  <li>ThePhD</li>
  <li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
  BUGS</a></h1>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
  tracker</a>
<div class="Pp"></div>
febug mailing list:
  &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
  archived at
  <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></div>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<p class="Pp">febug mailing list:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    archived at
    <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">FEBUG</td>

M Debian/index.0 => Debian/index.0 +2 -2
@@ 1,11 1,11 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "index" "0" "January 31, 2021" "Debian" "0"
.TH "index" "0" "March 7, 2021" "Debian" "0"
.nh
.if n .ad l
.SH "NAME"
\fBindex\fR
\- febug version 0.1.2 manpages
\- febug version 0.1.2-3-g82a6323 manpages
.SH "SEE ALSO"
febug(8)
\[u2013] User-space debugfs filesystem driver

M Debian/index.0.html => Debian/index.0.html +26 -22
@@ 314,27 314,29 @@ html {		--bg: #1E1F21;
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">index</code> &#x2014;
<div class="Nd">febug version 0.1.2 manpages</div>
<div class="Nd">febug version 0.1.2-3-g82a6323 manpages</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="febug.8.html">febug(8)</a> &#x2013; User-space debugfs filesystem
  driver
<div class="Pp"></div>
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2013; User-space debugfs ABI
<div class="Pp"></div>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2013; User-space debugfs ABI wrapper
  library
<div class="Pp"></div>
<a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2013; User-space debugfs ABI
  wrapper library for C++
<div class="Pp"></div>
<a class="Xr" href="libfebug.rs.3.html">libfebug.rs(3)</a> &#x2013; User-space debugfs ABI
  wrapper library for Rust
<a class="Xr" href="febug.8.html">febug(8)</a> &#x2013; User-space debugfs filesystem driver
<p class="Pp"><a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2013; User-space debugfs ABI</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2013; User-space debugfs ABI
    wrapper library</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2013; User-space debugfs ABI
    wrapper library for C++</p>
<p class="Pp"><a class="Xr" href="libfebug.rs.3.html">libfebug.rs(3)</a> &#x2013; User-space debugfs ABI
    wrapper library for Rust</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:


@@ 342,18 344,20 @@ To all who support further development, in particular:
  <li>ThePhD</li>
  <li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
  BUGS</a></h1>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
  tracker</a>
<div class="Pp"></div>
febug mailing list:
  &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
  archived at
  <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></div>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<p class="Pp">febug mailing list:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    archived at
    <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">January 31, 2021</td>
    <td class="foot-date">March 7, 2021</td>
    <td class="foot-os">Debian</td>
  </tr>
</table>

M Debian/libfebug++.3 => Debian/libfebug++.3 +1 -1
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG++" "3" "January 31, 2021" "Debian" "Library Functions Manual"
.TH "LIBFEBUG++" "3" "March 7, 2021" "Debian" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"

M Debian/libfebug++.3.html => Debian/libfebug++.3.html +186 -200
@@ 314,79 314,68 @@ html {		--bg: #1E1F21;
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug::controlled_socket</code>,
  <code class="Nm">febug::wrapper</code>,
  <code class="Nm">febug::formatters</code>,
  <code class="Nm">febug::debug_handler()</code> &#x2014;
<div class="Nd">User-space debugfs ABI wrapper library for C++</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<code class="In">#include
  &lt;<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/libfebug.hpp">libfebug.hpp</a>&gt;</code>
<div class="Pp"></div>
<span class="Lb">library &#x201C;libfebug++&#x201D;</span>
<div class="Pp"></div>
<br/>
<code class="Fd">#define FEBUG_DONT 0</code>
<br/>
<code class="Fd">#define FEBUG_SOCKET
  &quot;/run/febug.sock&quot;</code>
<br/>
<code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code>
<div class="Pp"></div>
<br/>
<code class="Fd">getenv(&quot;FEBUG_DONT&quot;)</code>
<br/>
<code class="Fd">getenv(&quot;FEBUG_SOCKET&quot;)</code>
<div class="Pp"></div>
<b class="Sy">struct febug::controlled_socket;</b>
<br/>
<var class="Vt">const febug::controlled_socket
  febug::global_controlled_socket;</var>
<div class="Pp"></div>
<b class="Sy">struct febug::wrapper;</b>
<br/>
<code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
  T &amp; data</var>,
  <var class="Fa" style="white-space: nowrap;">const char *
  name</var>,
  <var class="Fa" style="white-space: nowrap;">...</var>);
<div class="Pp"></div>
<code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
  T &amp; data</var>,
  <var class="Fa" style="white-space: nowrap;">uint8_t signal</var>,
  <var class="Fa" style="white-space: nowrap;">const char *
  name</var>,
  <var class="Fa" style="white-space: nowrap;">...</var>);
<div class="Pp"></div>
<code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
  T &amp; data</var>,
  <var class="Fa" style="white-space: nowrap;">uint8_t signal</var>,
  <var class="Fa" style="white-space: nowrap;">const char *
  name</var>, <var class="Fa" style="white-space: nowrap;">va_list
  ap</var>);
<div class="Pp"></div>
<var class="Vt">std::map&lt;size_t, void (*)(int, size_t)&gt;
  febug::formatters;</var>
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug::debug_handler</code>(<var class="Fa" style="white-space: nowrap;">int</var>);
<p class="Pp"><span class="Lb">library &#x201C;libfebug++&#x201D;</span></p>
<p class="Pp">
  <br/>
  <code class="Fd">#define FEBUG_DONT 0</code>
  <br/>
  <code class="Fd">#define FEBUG_SOCKET &quot;/run/febug.sock&quot;</code>
  <br/>
  <code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code></p>
<p class="Pp">
  <br/>
  <code class="Fd">getenv(&quot;FEBUG_DONT&quot;)</code>
  <br/>
  <code class="Fd">getenv(&quot;FEBUG_SOCKET&quot;)</code></p>
<p class="Pp"><b class="Sy">struct febug::controlled_socket;</b>
  <br/>
  <var class="Vt">const febug::controlled_socket
    febug::global_controlled_socket;</var></p>
<p class="Pp"><b class="Sy">struct febug::wrapper;</b>
  <br/>
  <code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
    T &amp; data</var>, <var class="Fa" style="white-space: nowrap;">const char
    * name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
    T &amp; data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><code class="Fn">febug::wrapper::wrapper</code>(<var class="Fa" style="white-space: nowrap;">const
    T &amp; data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">va_list
  ap</var>);</p>
<p class="Pp"><var class="Vt">std::map&lt;size_t, void (*)(int, size_t)&gt;
    febug::formatters;</var></p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug::debug_handler</code>(<var class="Fa" style="white-space: nowrap;">int</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<b class="Sy">libfebug++</b> allows a programmer to simplify writing
  C++ programs debuggable with <a class="Xr" href="febug.8.html">febug(8)</a> by
  presenting a high-level interface to
  <a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.
<div class="Pp"></div>
There are three compile-time macros that allow a program to customise its
  behaviour:
<b class="Sy">libfebug++</b> allows a programmer to simplify writing C++
  programs debuggable with <a class="Xr" href="febug.8.html">febug(8)</a> by presenting a high-level
  interface to <a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.
<p class="Pp">There are three compile-time macros that allow a program to
    customise its behaviour:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><code class="Fd">FEBUG_DONT</code> If non-zero, all symbols
      become <b class="Sy">static</b>, functions turn into no-ops,
      and therefore no symbols from libfebug++.a/.so are imported at link-time;
      this is intended as a way to easily disable
      <a class="Xr" href="febug.8.html">febug(8)</a> integration completely on release
      builds.</dd>
  <dd><code class="Fd">FEBUG_DONT</code> If non-zero, all symbols become
      <b class="Sy">static</b>, functions turn into no-ops, and therefore no
      symbols from libfebug++.a/.so are imported at link-time; this is intended
      as a way to easily disable <a class="Xr" href="febug.8.html">febug(8)</a> integration
      completely on release builds.</dd>
  <dt></dt>
  <dd><code class="Fd">FEBUG_SIGNUM</code> The signal to request from
      <a class="Xr" href="febug.8.html">febug(8)</a> when using


@@ 397,160 386,155 @@ There are three compile-time macros that allow a program to customise its
      <a class="Xr" href="febug.8.html">febug(8)</a> on. Defaults to
      <span class="Pa">/run/febug.sock</span>.</dd>
</dl>
<div class="Pp"></div>
There are two environment variables that allow a user to customise its
  behaviour:
<p class="Pp">There are two environment variables that allow a user to customise
    its behaviour:</p>
<dl class="Bl-tag">
  <dt><i class="Em">FEBUG_DONT</i></dt>
  <dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so
      all library functions become no-ops.</dd>
  <dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so all library
      functions become no-ops.</dd>
  <dt><i class="Em">FEBUG_SOCKET</i></dt>
  <dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b>
      to connect to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
  <dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b> to connect
      to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<div class="Pp"></div>
The <b class="Sy">febug::controlled_socket</b> structure is defined
  as follows:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
struct febug::controlled_socket { 
    int fd = -1; 
    inline operator int() const noexcept { return this-&gt;fd; } 
    controlled_socket(const char * path = FEBUG_SOCKET) noexcept; 
    ~controlled_socket() noexcept; 
<p class="Pp">The <b class="Sy">febug::controlled_socket</b> structure is
    defined as follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
struct febug::controlled_socket {
    int fd = -1;
    inline operator int() const noexcept { return this-&gt;fd; }
    controlled_socket(const char * path = FEBUG_SOCKET) noexcept;
    ~controlled_socket() noexcept;
};
</pre>
</div>
<div class="Pp"></div>
There is a global instance at
  <var class="Vt">febug::global_controlled_socket</var> which, if
  <var class="Vt">path</var> isn't the null pointer, attempts
  connection to <a class="Xr" href="febug.8.html">febug(8)</a> and will set
  <var class="Vt">fd</var>, if successful. Similarly, destroying it
  will hang up and reset <var class="Vt">fd</var>.
<div class="Pp"></div>
The program needs to install
  <code class="Fn">febug::debug_handler</code>() (or a wrapper around
  it) as the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (and
  any other signals, if different ones are explicitly requested; if
  <code class="Dv">SIGKILL</code>, some event loop that answers on
  <var class="Vt">febug::global_controlled_socket</var> must be in
  place). It's a no-op if
  <var class="Vt">febug::global_controlled_socket</var> is -1. This
  finishes set-up.
<div class="Pp"></div>
The program should register handlers for types of variables it wishes to handle
  by adding entries to <var class="Vt">febug::formatters</var>
  &#x2014; the key is typeid(std::decay_t&lt;T&gt;).hash_code(), so if this
  yields different results for two types that should have the same handler,
  multiple entries need to be registered. If no handler was registered for a
  type, <code class="Fn">febug::debug_handler</code>() will write a
  generic &quot;not found&quot; 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
  <code class="Fn">febug::debug_handler</code>() regardless, and the
  program would then run the risk of closing another file with the same
  descriptor simultaneously opened by another thread.
<div class="Pp"></div>
The <b class="Sy">febug::wrapper</b> structure is defined as follows:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
template &lt;class T&gt; 
struct febug::wrapper { 
    const T * data; 
    wrapper(const T &amp; data, const char * name, ...) noexcept; 
    wrapper(const T &amp; data, uint8_t signal, const char * name, ...) noexcept; 
    wrapper(const T &amp; data, uint8_t signal, const char * name, va_list ap) noexcept; 
    ~wrapper() noexcept; 
<p class="Pp">There is a global instance at
    <var class="Vt">febug::global_controlled_socket</var> which, if
    <var class="Vt">path</var> isn't the null pointer, attempts connection to
    <a class="Xr" href="febug.8.html">febug(8)</a> and will set <var class="Vt">fd</var>, if
    successful. Similarly, destroying it will hang up and reset
    <var class="Vt">fd</var>.</p>
<p class="Pp">The program needs to install
    <code class="Fn">febug::debug_handler</code>() (or a wrapper around it) as
    the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (and any other
    signals, if different ones are explicitly requested; if
    <code class="Dv">SIGKILL</code>, some event loop that answers on
    <var class="Vt">febug::global_controlled_socket</var> must be in place).
    It's a no-op if <var class="Vt">febug::global_controlled_socket</var> is -1.
    This finishes set-up.</p>
<p class="Pp">The program should register handlers for types of variables it
    wishes to handle by adding entries to
    <var class="Vt">febug::formatters</var> &#x2014; the key is
    typeid(std::decay_t&lt;T&gt;).hash_code(), so if this yields different
    results for two types that should have the same handler, multiple entries
    need to be registered. If no handler was registered for a type,
    <code class="Fn">febug::debug_handler</code>() will write a generic
    &quot;not found&quot; 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 <code class="Fn">febug::debug_handler</code>()
    regardless, and the program would then run the risk of closing another file
    with the same descriptor simultaneously opened by another thread.</p>
<p class="Pp">The <b class="Sy">febug::wrapper</b> structure is defined as
    follows:</p>
<div class="Bd Pp Bd-indent">
<pre>
template &lt;class T&gt;
struct febug::wrapper {
    const T * data;
    wrapper(const T &amp; data, const char * name, ...) noexcept;
    wrapper(const T &amp; data, uint8_t signal, const char * name, ...) noexcept;
    wrapper(const T &amp; data, uint8_t signal, const char * name, va_list ap) noexcept;
    ~wrapper() noexcept;
};
</pre>
</div>
<div class="Pp"></div>
If the program wishes to debug a variable, it should construct a
  <b class="Sy">febug::wrapper</b> referencing it; the constructor
  will send a <b class="Sy">febug_message</b> with the type
  corresponding to
  <code class="Dv">typeid(std::decay_t&lt;T&gt;).hash_code()</code>,
  ID corresponding to the pointer to <var class="Vt">data</var>,
  signal being either specified or defaulting to
  <code class="Fd">FEBUG_SIGNUM,</code> and name formatted according
  to <a class="Xr">printf(3)</a>. The destructor will send a
  <b class="Sy">stop_febug_message</b>. Both become no-ops if
  <var class="Vt">febug::global_controlled_socket</var> is -1.
<p class="Pp">If the program wishes to debug a variable, it should construct a
    <b class="Sy">febug::wrapper</b> referencing it; the constructor will send a
    <b class="Sy">febug_message</b> with the type corresponding to
    <code class="Dv">typeid(std::decay_t&lt;T&gt;).hash_code()</code>, ID
    corresponding to the pointer to <var class="Vt">data</var>, signal being
    either specified or defaulting to <code class="Fd">FEBUG_SIGNUM,</code> and
    name formatted according to <a class="Xr">printf(3)</a>. The destructor will
    send a <b class="Sy">stop_febug_message</b>. Both become no-ops if
    <var class="Vt">febug::global_controlled_socket</var> is -1.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
The following program sorts a std::vector&lt;int&gt; with
  <code class="Fn">std::sort</code>() but waits a second between each
  comparison; the vector and the amount of comparisons can be inspected via a
  <a class="Xr" href="febug.8.html">febug(8)</a> mount:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
// SPDX-License-Identifier: MIT 
 
 
#include &lt;libfebug.hpp&gt; 
 
#include &lt;vector&gt; 
 
#include &lt;algorithm&gt; 
#include &lt;cstring&gt; 
#include &lt;errno.h&gt; 
 
#include &lt;unistd.h&gt; 
 
 
int main() { 
	if(febug::global_controlled_socket != -1) { 
		febug::formatters.emplace(typeid(std::vector&lt;int&gt;).hash_code(), [](int retpipe, std::size_t vid) { 
			const std::vector&lt;int&gt; &amp; data = *(const std::vector&lt;int&gt; *)vid; 
			for(auto num : data) 
				dprintf(retpipe, &quot;%d &quot;, num); 
			write(retpipe, &quot;0, 1); 
		}); 
		febug::formatters.emplace(typeid(std::size_t).hash_code(), [](int retpipe, std::size_t vid) { 
			const std::size_t &amp; data = *(const std::size_t *)vid; 
			dprintf(retpipe, &quot;%zu0, data); 
		}); 
	} 
 
 
	struct sigaction handler {}; 
	handler.sa_handler = febug::debug_handler; 
	if(sigaction(FEBUG_SIGNUM, &amp;handler, nullptr) == -1) 
		std::fprintf(stderr, &quot;sigaction: %s0, std::strerror(errno)); 
 
 
	{ 
		std::vector&lt;int&gt; data{-1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, 
		                      -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3}; 
		std::size_t comparisons_done{}; 
		febug::wrapper data_w{data, &quot;cool_data&quot;}; 
		febug::wrapper comparisons_done_w{comparisons_done, &quot;comparisons&quot;}; 
 
		std::sort(data.begin(), data.end(), [&amp;](auto lhs, auto rhs) { 
			sleep(1); 
			++comparisons_done; 
			return lhs &lt; rhs; 
		}); 
	} 
 
	sleep(2); 
<div class="Bd Pp Bd-indent">
<pre>
// SPDX-License-Identifier: MIT


#include &lt;libfebug.hpp&gt;

#include &lt;vector&gt;

#include &lt;algorithm&gt;
#include &lt;cstring&gt;
#include &lt;errno.h&gt;

#include &lt;unistd.h&gt;


int main() {
	if(febug::global_controlled_socket != -1) {
		febug::formatters.emplace(typeid(std::vector&lt;int&gt;).hash_code(), [](int retpipe, std::size_t vid) {
			const std::vector&lt;int&gt; &amp; data = *(const std::vector&lt;int&gt; *)vid;
			for(auto num : data)
				dprintf(retpipe, &quot;%d &quot;, num);
			write(retpipe, &quot;0, 1);
		});
		febug::formatters.emplace(typeid(std::size_t).hash_code(), [](int retpipe, std::size_t vid) {
			const std::size_t &amp; data = *(const std::size_t *)vid;
			dprintf(retpipe, &quot;%zu0, data);
		});
	}


	struct sigaction handler {};
	handler.sa_handler = febug::debug_handler;
	if(sigaction(FEBUG_SIGNUM, &amp;handler, nullptr) == -1)
		std::fprintf(stderr, &quot;sigaction: %s0, std::strerror(errno));


	{
		std::vector&lt;int&gt; data{-1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3,
		                      -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3, -1, -2, -3, 0, 1, 2, 3};
		std::size_t comparisons_done{};
		febug::wrapper data_w{data, &quot;cool_data&quot;};
		febug::wrapper comparisons_done_w{comparisons_done, &quot;comparisons&quot;};

		std::sort(data.begin(), data.end(), [&amp;](auto lhs, auto rhs) {
			sleep(1);
			++comparisons_done;
			return lhs &lt; rhs;
		});
	}

	sleep(2);
}
</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this
  library.
<div class="Pp"></div>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent C library.
<div class="Pp"></div>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent Rust library.
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this library.
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent C
  library.</p>
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent Rust
  library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:


@@ 558,18 542,20 @@ To all who support further development, in particular:
  <li>ThePhD</li>
  <li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
  BUGS</a></h1>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
  tracker</a>
<div class="Pp"></div>
febug mailing list:
  &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
  archived at
  <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></div>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<p class="Pp">febug mailing list:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    archived at
    <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">January 31, 2021</td>
    <td class="foot-date">March 7, 2021</td>
    <td class="foot-os">Debian</td>
  </tr>
</table>

M Debian/libfebug.3 => Debian/libfebug.3 +1 -1
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG" "3" "January 31, 2021" "Debian" "Library Functions Manual"
.TH "LIBFEBUG" "3" "March 7, 2021" "Debian" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"

M Debian/libfebug.3.html => Debian/libfebug.3.html +205 -217
@@ 314,95 314,84 @@ html {		--bg: #1E1F21;
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug_start()</code>,
  <code class="Nm">febug_end()</code>,
<code class="Nm">febug_start()</code>, <code class="Nm">febug_end()</code>,
  <code class="Nm">febug_register_type()</code>,
  <code class="Nm">febug_wrap()</code>,
  <code class="Nm">febug_unwrap()</code> &#x2014;
  <code class="Nm">febug_wrap()</code>, <code class="Nm">febug_unwrap()</code>
  &#x2014;
<div class="Nd">User-space debugfs ABI wrapper library</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<code class="In">#include
  &lt;<a class="In" href="https://git.sr.ht/~nabijaczleweli/febug/tree/trunk/item/include/libfebug.h">libfebug.h</a>&gt;</code>
<div class="Pp"></div>
<span class="Lb">library &#x201C;libfebug&#x201D;</span>
<div class="Pp"></div>
<br/>
<code class="Fd">#define FEBUG_DONT 0</code>
<br/>
<code class="Fd">#define FEBUG_SOCKET
  &quot;/run/febug.sock&quot;</code>
<br/>
<code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code>
<div class="Pp"></div>
<br/>
<code class="Fd">getenv(&quot;FEBUG_DONT&quot;)</code>
<br/>
<code class="Fd">getenv(&quot;FEBUG_SOCKET&quot;)</code>
<div class="Pp"></div>
<br/>
<var class="Vt">int febug_global_controlled_socket</var> = -1;
<div class="Pp"></div>
<br/>
<var class="Ft">void</var>
  <code class="Fn">febug_start</code>();
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_start_path</code>(<var class="Fa" style="white-space: nowrap;">const
  char * path</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_debug_handler</code>(<var class="Fa" style="white-space: nowrap;">int</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_register_type</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
  type</var>, <var class="Fa" style="white-space: nowrap;">void
  (*formatter)(int, size_t)</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_wrap</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
  type</var>, <var class="Fa" style="white-space: nowrap;">const void
  * data</var>, <var class="Fa" style="white-space: nowrap;">const
  char * name</var>,
  <var class="Fa" style="white-space: nowrap;">...</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
  type</var>, <var class="Fa" style="white-space: nowrap;">const void
  * data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
  signal</var>, <var class="Fa" style="white-space: nowrap;">const
  char * name</var>,
  <var class="Fa" style="white-space: nowrap;">...</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_wrap_signalv</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
  type</var>, <var class="Fa" style="white-space: nowrap;">const void
  * data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
  signal</var>, <var class="Fa" style="white-space: nowrap;">const
  char * name</var>,
  <var class="Fa" style="white-space: nowrap;">va_list ap</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_unwrap</code>(<var class="Fa" style="white-space: nowrap;">const
  void * data</var>);
<div class="Pp"></div>
<var class="Ft">void</var>
  <code class="Fn">febug_end</code>();
<p class="Pp"><span class="Lb">library &#x201C;libfebug&#x201D;</span></p>
<p class="Pp">
  <br/>
  <code class="Fd">#define FEBUG_DONT 0</code>
  <br/>
  <code class="Fd">#define FEBUG_SOCKET &quot;/run/febug.sock&quot;</code>
  <br/>
  <code class="Fd">#define FEBUG_SIGNUM SIGUSR2</code></p>
<p class="Pp">
  <br/>
  <code class="Fd">getenv(&quot;FEBUG_DONT&quot;)</code>
  <br/>
  <code class="Fd">getenv(&quot;FEBUG_SOCKET&quot;)</code></p>
<p class="Pp">
  <br/>
  <var class="Vt">int febug_global_controlled_socket</var> = -1;</p>
<p class="Pp">
  <br/>
  <var class="Ft">void</var> <code class="Fn">febug_start</code>();</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_start_path</code>(<var class="Fa" style="white-space: nowrap;">const
    char * path</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_debug_handler</code>(<var class="Fa" style="white-space: nowrap;">int</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_register_type</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">void
    (*formatter)(int, size_t)</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_wrap</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">const void *
    data</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">const void *
    data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_wrap_signalv</code>(<var class="Fa" style="white-space: nowrap;">uint64_t
    type</var>, <var class="Fa" style="white-space: nowrap;">const void *
    data</var>, <var class="Fa" style="white-space: nowrap;">uint8_t
    signal</var>, <var class="Fa" style="white-space: nowrap;">const char *
    name</var>, <var class="Fa" style="white-space: nowrap;">va_list
  ap</var>);</p>
<p class="Pp"><var class="Ft">void</var>
    <code class="Fn">febug_unwrap</code>(<var class="Fa" style="white-space: nowrap;">const
    void * data</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <code class="Fn">febug_end</code>();</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<b class="Sy">libfebug</b> allows a programmer to simplify writing
  programs debuggable with <a class="Xr" href="febug.8.html">febug(8)</a> by presenting a
  high-level interface to <a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.
<div class="Pp"></div>
There are three compile-time macros that allow a program to customise its
  behaviour:
<b class="Sy">libfebug</b> allows a programmer to simplify writing programs
  debuggable with <a class="Xr" href="febug.8.html">febug(8)</a> by presenting a high-level
  interface to <a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.
<p class="Pp">There are three compile-time macros that allow a program to
    customise its behaviour:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><code class="Fd">FEBUG_DONT</code> If non-zero, all symbols
      become <b class="Sy">static</b>, functions turn into no-ops,
      and therefore no symbols from libfebug.a/.so are imported at link-time;
      this is intended as a way to easily disable
      <a class="Xr" href="febug.8.html">febug(8)</a> integration completely on release
      builds.</dd>
  <dd><code class="Fd">FEBUG_DONT</code> If non-zero, all symbols become
      <b class="Sy">static</b>, functions turn into no-ops, and therefore no
      symbols from libfebug.a/.so are imported at link-time; this is intended as
      a way to easily disable <a class="Xr" href="febug.8.html">febug(8)</a> integration completely
      on release builds.</dd>
  <dt></dt>
  <dd><code class="Fd">FEBUG_SIGNUM</code> The signal to request from
      <a class="Xr" href="febug.8.html">febug(8)</a> when using


@@ 413,148 402,145 @@ There are three compile-time macros that allow a program to customise its
      <a class="Xr" href="febug.8.html">febug(8)</a> on. Defaults to
      <span class="Pa">/run/febug.sock</span>.</dd>
</dl>
<div class="Pp"></div>
There are two environment variables that allow a user to customise its
  behaviour:
<p class="Pp">There are two environment variables that allow a user to customise
    its behaviour:</p>
<dl class="Bl-tag">
  <dt><i class="Em">FEBUG_DONT</i></dt>
  <dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so
      all library functions become no-ops.</dd>
  <dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so all library
      functions become no-ops.</dd>
  <dt><i class="Em">FEBUG_SOCKET</i></dt>
  <dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b>
      to connect to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
  <dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b> to connect
      to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<div class="Pp"></div>
To be debugged, a program needs to, first, call
  <code class="Fn">febug_start_path</code>() (likely via
  <code class="Fn">febug_start</code>(), which simply passes
  <code class="Fd">FEBUG_SOCKET</code> thereto) to connect to
  <a class="Xr" href="febug.8.html">febug(8)</a>, which, if successful, will set
  <var class="Vt">febug_global_controlled_socket</var> appropriately.
<div class="Pp"></div>
The program needs to install
  <code class="Fn">febug_debug_handler</code>() (or a wrapper around
  it) as the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (and
  any other signals, if different ones are explicitly requested; if
  <code class="Dv">SIGKILL</code>, some event loop that answers on
  <var class="Vt">febug_global_controlled_socket</var> must be in
  place). It's a no-op if
  <var class="Vt">febug_global_controlled_socket</var> is -1. This
  finishes set-up.
<div class="Pp"></div>
The program should register handlers for types of variables it wishes to handle
  by calling <code class="Fn">febug_register_type</code>() &#x2014;
  those type numbers should be consistent across the program, lest the wrong
  handler is called. If no handler was registered for a type,
  <code class="Fn">febug_debug_handler</code>() will write a generic
  &quot;not found&quot; 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
  <code class="Fn">febug_debug_handler</code>() 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
  <var class="Vt">febug_global_controlled_socket</var> is -1.
<div class="Pp"></div>
At any time, when the program wishes to expose a variable, it can call
  <code class="Fn">febug_wrap_signalv</code>() (likely via
  <code class="Fn">febug_wrap_signal</code>() (likely via
  <code class="Fn">febug_wrap</code>(), which passes
  <b class="Sy">FEBUG_SIGNUM</b> thereto)), which will send a
  <b class="Sy">febug_message</b> with the specified type and signal
  numbers, ID equal to the data pointer, and name formatted according to
  <a class="Xr">printf(3)</a>. It's a no-op if
  <var class="Vt">febug_global_controlled_socket</var> is -1.
<div class="Pp"></div>
When the variable goes out of scope, the program should call
  <code class="Fn">febug_unwrap</code>() to send a
  <b class="Sy">stop_febug_message</b> with the same data pointer as
  it did <code class="Fn">febug_wrap</code>(), to prevent reading
  random data that might no longer be mapped, or make sense. It's a no-op if
  <var class="Vt">febug_global_controlled_socket</var> is -1.
<div class="Pp"></div>
When it wishes to stop being debugged, the program may call
  <code class="Fn">febug_end</code>() which will shutter and reset
  <var class="Vt">febug_global_controlled_socket</var>, if any, and
  deallocate the type-&gt;handler map. 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.
<p class="Pp">To be debugged, a program needs to, first, call
    <code class="Fn">febug_start_path</code>() (likely via
    <code class="Fn">febug_start</code>(), which simply passes
    <code class="Fd">FEBUG_SOCKET</code> thereto) to connect to
    <a class="Xr" href="febug.8.html">febug(8)</a>, which, if successful, will set
    <var class="Vt">febug_global_controlled_socket</var> appropriately.</p>
<p class="Pp">The program needs to install
    <code class="Fn">febug_debug_handler</code>() (or a wrapper around it) as
    the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (and any other
    signals, if different ones are explicitly requested; if
    <code class="Dv">SIGKILL</code>, some event loop that answers on
    <var class="Vt">febug_global_controlled_socket</var> must be in place). It's
    a no-op if <var class="Vt">febug_global_controlled_socket</var> is -1. This
    finishes set-up.</p>
<p class="Pp">The program should register handlers for types of variables it
    wishes to handle by calling <code class="Fn">febug_register_type</code>()
    &#x2014; those type numbers should be consistent across the program, lest
    the wrong handler is called. If no handler was registered for a type,
    <code class="Fn">febug_debug_handler</code>() will write a generic &quot;not
    found&quot; 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 <code class="Fn">febug_debug_handler</code>()
    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 <var class="Vt">febug_global_controlled_socket</var> is -1.</p>
<p class="Pp">At any time, when the program wishes to expose a variable, it can
    call <code class="Fn">febug_wrap_signalv</code>() (likely via
    <code class="Fn">febug_wrap_signal</code>() (likely via
    <code class="Fn">febug_wrap</code>(), which passes
    <b class="Sy">FEBUG_SIGNUM</b> thereto)), which will send a
    <b class="Sy">febug_message</b> with the specified type and signal numbers,
    ID equal to the data pointer, and name formatted according to
    <a class="Xr">printf(3)</a>. It's a no-op if
    <var class="Vt">febug_global_controlled_socket</var> is -1.</p>
<p class="Pp">When the variable goes out of scope, the program should call
    <code class="Fn">febug_unwrap</code>() to send a
    <b class="Sy">stop_febug_message</b> with the same data pointer as it did
    <code class="Fn">febug_wrap</code>(), to prevent reading random data that
    might no longer be mapped, or make sense. It's a no-op if
    <var class="Vt">febug_global_controlled_socket</var> is -1.</p>
<p class="Pp">When it wishes to stop being debugged, the program may call
    <code class="Fn">febug_end</code>() which will shutter and reset
    <var class="Vt">febug_global_controlled_socket</var>, if any, and deallocate
    the type-&gt;handler map. 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.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
The following program sorts a string with <a class="Xr">qsort(3)</a>
  but waits half a second between each comparison; the string can be inspected
  via a <a class="Xr" href="febug.8.html">febug(8)</a> mount:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
// SPDX-License-Identifier: MIT 
 
 
#define _POSIX_C_SOURCE 200809L 
 
#include &lt;libfebug.h&gt; 
 
#include &lt;signal.h&gt; 
 
#include &lt;stdio.h&gt; 
#include &lt;stdlib.h&gt; 
#include &lt;string.h&gt; 
#include &lt;time.h&gt; 
#include &lt;errno.h&gt; 
#include &lt;unistd.h&gt; 
 
 
#define CSTRING_FEBUG_TP 420 
static void cstring_febug_formatter(int fd, size_t data) { 
	const char * str = (const char *)data; 
	dprintf(fd, &quot;%s0, str); 
} 
 
 
static int char_comp(const void * lhs, const void * rhs) { 
	const struct timespec half_second = {0, 500 * 1000 * 1000}; 
	nanosleep(&amp;half_second, 0); 
 
	return *(const char *)lhs - *(const char *)rhs; 
} 
 
 
int main() { 
	febug_start(); 
	febug_register_type(CSTRING_FEBUG_TP, cstring_febug_formatter); 
 
 
	struct sigaction handler; 
	memset(&amp;handler, 0, sizeof(handler)); 
	handler.sa_handler = febug_debug_handler; 
	if(sigaction(FEBUG_SIGNUM, &amp;handler, 0) == -1) { 
		fprintf(stderr, &quot;sigaction: %s0, strerror(errno)); 
		return 1; 
	} 
 
 
	{ 
		__attribute__((__cleanup__(febug_unwrap))) char data[] = &quot;JVLOkgsYmhCyEFxouKzDNajivGlpWqbdBwnfTAXQcreRHPIUSMtZQWERTYUIOPqwertyuiop1234567890&quot;; 
		febug_wrap(CSTRING_FEBUG_TP, data, &quot;cool_data&quot;); 
 
		qsort(data, strlen(data), 1, char_comp); 
	} 
 
	sleep(2); 
 
	febug_end(); 
The following program sorts a string with <a class="Xr">qsort(3)</a> but waits
  half a second between each comparison; the string can be inspected via a
  <a class="Xr" href="febug.8.html">febug(8)</a> mount:
<div class="Bd Pp Bd-indent">
<pre>
// SPDX-License-Identifier: MIT


#define _POSIX_C_SOURCE 200809L

#include &lt;libfebug.h&gt;

#include &lt;signal.h&gt;

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;time.h&gt;
#include &lt;errno.h&gt;
#include &lt;unistd.h&gt;


#define CSTRING_FEBUG_TP 420
static void cstring_febug_formatter(int fd, size_t data) {
	const char * str = (const char *)data;
	dprintf(fd, &quot;%s0, str);
}


static int char_comp(const void * lhs, const void * rhs) {
	const struct timespec half_second = {0, 500 * 1000 * 1000};
	nanosleep(&amp;half_second, 0);

	return *(const char *)lhs - *(const char *)rhs;
}


int main() {
	febug_start();
	febug_register_type(CSTRING_FEBUG_TP, cstring_febug_formatter);


	struct sigaction handler;
	memset(&amp;handler, 0, sizeof(handler));
	handler.sa_handler = febug_debug_handler;
	if(sigaction(FEBUG_SIGNUM, &amp;handler, 0) == -1) {
		fprintf(stderr, &quot;sigaction: %s0, strerror(errno));
		return 1;
	}


	{
		__attribute__((__cleanup__(febug_unwrap))) char data[] = &quot;JVLOkgsYmhCyEFxouKzDNajivGlpWqbdBwnfTAXQcreRHPIUSMtZQWERTYUIOPqwertyuiop1234567890&quot;;
		febug_wrap(CSTRING_FEBUG_TP, data, &quot;cool_data&quot;);

		qsort(data, strlen(data), 1, char_comp);
	}

	sleep(2);

	febug_end();
}
</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this
  library.
<div class="Pp"></div>
<a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent C++ library.
<div class="Pp"></div>
<a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent Rust library.
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this library.
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent C++
    library.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent Rust
    library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:


@@ 562,18 548,20 @@ To all who support further development, in particular:
  <li>ThePhD</li>
  <li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
  BUGS</a></h1>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
  tracker</a>
<div class="Pp"></div>
febug mailing list:
  &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
  archived at
  <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></div>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<p class="Pp">febug mailing list:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    archived at
    <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">January 31, 2021</td>
    <td class="foot-date">March 7, 2021</td>
    <td class="foot-os">Debian</td>
  </tr>
</table>

M Debian/libfebug.rs.3 => Debian/libfebug.rs.3 +2 -2
@@ 1,6 1,6 @@
.\" Automatically generated from an mdoc input file.  Do not edit.
.\"" SPDX-License-Identifier: MIT
.TH "LIBFEBUG.RS" "3" "January 31, 2021" "Debian" "Library Functions Manual"
.TH "LIBFEBUG.RS" "3" "March 7, 2021" "Debian" "Library Functions Manual"
.nh
.if n .ad l
.SH "NAME"


@@ 15,7 15,7 @@
.nf
.RS 0n
[dependencies]
febug = "0.1.2"
febug = "0.1.2-3-g82a6323"
.RE
.fi
.PP

M Debian/libfebug.rs.3.html => Debian/libfebug.rs.3.html +214 -230
@@ 314,131 314,115 @@ html {		--bg: #1E1F21;
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">febug::start()</code>,
  <code class="Nm">febug::Wrapper</code>,
<code class="Nm">febug::start()</code>, <code class="Nm">febug::Wrapper</code>,
  <code class="Nm">febug::Wrappable</code>,
  <code class="Nm">febug::StaticWrappable</code>,
  <code class="Nm">febug::GLOBAL_CONTROLLED_SOCKET</code>,
  <code class="Nm">febug::FORMATTERS</code> &#x2014;
<div class="Nd">User-space debugfs ABI wrapper library for Rust</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<div class="Bd">
<pre class="Li">
[dependencies] 
febug = &quot;0.1.2&quot;
<pre>
[dependencies]
febug = &quot;0.1.2-3-g82a6323&quot;
</pre>
</div>
<div class="Pp"></div>
<br/>
<code class="Fd">env!(&quot;FEBUG_DONT&quot;)?</code>
<br/>
<code class="Fd">env!(&quot;FEBUG_SOCKET&quot;) =
  &quot;/run/febug.sock&quot;</code>
<br/>
<code class="Fd">env!(&quot;FEBUG_SIGNUM&quot;) = SIGUSR2</code>
<div class="Pp"></div>
<br/>
<code class="Fd">env::var(&quot;FEBUG_DONT&quot;)</code>
<br/>
<code class="Fd">env::var(&quot;FEBUG_SOCKET&quot;)</code>
<div class="Pp"></div>
<br/>
<var class="Vt">static GLOBAL_CONTROLLED_SOCKET: AtomicI32</var> =
  -1;
<div class="Pp"></div>
<br/>
<var class="Ft">fn</var>
  <code class="Fn">febug::start</code>();
<div class="Pp"></div>
<var class="Ft">fn</var>
  <code class="Fn">febug::start_raw</code>(<var class="Fa" style="white-space: nowrap;">path:
  &amp;[u8]</var>);
<div class="Pp"></div>
<var class="Ft">extern 'C' fn</var>
  <code class="Fn">debug_handler</code>(<var class="Fa" style="white-space: nowrap;">_:
  c_int</var>);
<div class="Pp"></div>
<var class="Ft">bool fn</var>
  <code class="Fn">febug::install_handler</code>();
<div class="Pp"></div>
<var class="Ft">bool fn</var>
  <code class="Fn">febug::install_handler_signal</code>(<var class="Fa" style="white-space: nowrap;">signal:
  u8</var>);
<div class="Pp"></div>
<var class="Ft">fn</var>
  <code class="Fn">febug::end</code>();
<div class="Pp"></div>
<var class="Vt">static febug::FORMATTERS:
  Lazy&lt;Mutex&lt;BTreeMap&lt;TypeId, fn(&amp;mut File,
  usize)&gt;&gt;&gt;</var>
<div class="Pp"></div>
<b class="Sy">trait febug::StaticWrappable: 'static;</b>
<br/>
<var class="Ft">Wrapper&lt;Self&gt; fn</var>
  <code class="Fn">febug::StaticWrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  Arguments&lt;'_&gt;</var>);
<div class="Pp"></div>
<var class="Ft">Wrapper&lt;Self&gt; fn</var>
  <code class="Fn">febug::StaticWrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
  <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  Arguments&lt;'_&gt;</var>);
<div class="Pp"></div>
<b class="Sy">trait febug::Wrappable;</b>
<br/>
<var class="Ft">Wrapper&lt;Self&gt; fn</var>
  <code class="Fn">febug::Wrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
  <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  Arguments&lt;'_&gt;</var>);
<div class="Pp"></div>
<var class="Ft">Wrapper&lt;Self&gt; fn</var>
  <code class="Fn">febug::Wrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
  <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
  <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  Arguments&lt;'_&gt;</var>);
<div class="Pp"></div>
<b class="Sy">struct febug::Wrapper&lt;T&gt;</b> { /* &#x2026; */ };
<br/>
<var class="Ft">Wrapper&lt;T&gt; fn</var>
  <code class="Fn">febug::Wrapper::new</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
  <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
  <var class="Fa" style="white-space: nowrap;">data:argument</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  fmt::Arguments</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  Arguments&lt;'_&gt;</var>);
<div class="Pp"></div>
<var class="Ft">Wrapper&lt;T&gt; fn</var>
  <code class="Fn">febug::Wrapper::new_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
  <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
  <var class="Fa" style="white-space: nowrap;">data:argument</var>,
  <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  fmt::Arguments</var>,
  <var class="Fa" style="white-space: nowrap;">name:
  Arguments&lt;'_&gt;</var>);
<div class="Pp"></div>
<b class="Sy">struct febug::abi::FebugMessage;</b>
  <b class="Sy">struct febug::abi::StopFebugMessage;</b>
  <b class="Sy">struct febug::abi::AttnFebugMessage;</b>
<p class="Pp">
  <br/>
  <code class="Fd">env!(&quot;FEBUG_DONT&quot;)?</code>
  <br/>
  <code class="Fd">env!(&quot;FEBUG_SOCKET&quot;) =
    &quot;/run/febug.sock&quot;</code>
  <br/>
  <code class="Fd">env!(&quot;FEBUG_SIGNUM&quot;) = SIGUSR2</code></p>
<p class="Pp">
  <br/>
  <code class="Fd">env::var(&quot;FEBUG_DONT&quot;)</code>
  <br/>
  <code class="Fd">env::var(&quot;FEBUG_SOCKET&quot;)</code></p>
<p class="Pp">
  <br/>
  <var class="Vt">static GLOBAL_CONTROLLED_SOCKET: AtomicI32</var> = -1;</p>
<p class="Pp">
  <br/>
  <var class="Ft">fn</var> <code class="Fn">febug::start</code>();</p>
<p class="Pp"><var class="Ft">fn</var>
    <code class="Fn">febug::start_raw</code>(<var class="Fa" style="white-space: nowrap;">path:
    &amp;[u8]</var>);</p>
<p class="Pp"><var class="Ft">extern 'C' fn</var>
    <code class="Fn">debug_handler</code>(<var class="Fa" style="white-space: nowrap;">_:
    c_int</var>);</p>
<p class="Pp"><var class="Ft">bool fn</var>
    <code class="Fn">febug::install_handler</code>();</p>
<p class="Pp"><var class="Ft">bool fn</var>
    <code class="Fn">febug::install_handler_signal</code>(<var class="Fa" style="white-space: nowrap;">signal:
    u8</var>);</p>
<p class="Pp"><var class="Ft">fn</var> <code class="Fn">febug::end</code>();</p>
<p class="Pp"><var class="Vt">static febug::FORMATTERS:
    Lazy&lt;Mutex&lt;BTreeMap&lt;TypeId, fn(&amp;mut File,
    usize)&gt;&gt;&gt;</var></p>
<p class="Pp"><b class="Sy">trait febug::StaticWrappable: 'static;</b>
  <br/>
  <var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::StaticWrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::StaticWrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><b class="Sy">trait febug::Wrappable;</b>
  <br/>
  <var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::Wrappable::wrap</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><var class="Ft">Wrapper&lt;Self&gt; fn</var>
    <code class="Fn">febug::Wrappable::wrap_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
    <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><b class="Sy">struct febug::Wrapper&lt;T&gt;</b> { /* &#x2026; */
    };
  <br/>
  <var class="Ft">Wrapper&lt;T&gt; fn</var>
    <code class="Fn">febug::Wrapper::new</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
    <var class="Fa" style="white-space: nowrap;">data:argument</var>,
    <var class="Fa" style="white-space: nowrap;">name: fmt::Arguments</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><var class="Ft">Wrapper&lt;T&gt; fn</var>
    <code class="Fn">febug::Wrapper::new_signal</code>(<var class="Fa" style="white-space: nowrap;">&amp;self</var>,
    <var class="Fa" style="white-space: nowrap;">tp: u64</var>,
    <var class="Fa" style="white-space: nowrap;">data:argument</var>,
    <var class="Fa" style="white-space: nowrap;">signal: u8</var>,
    <var class="Fa" style="white-space: nowrap;">name: fmt::Arguments</var>,
    <var class="Fa" style="white-space: nowrap;">name:
    Arguments&lt;'_&gt;</var>);</p>
<p class="Pp"><b class="Sy">struct febug::abi::FebugMessage;</b>
    <b class="Sy">struct febug::abi::StopFebugMessage;</b> <b class="Sy">struct
    febug::abi::AttnFebugMessage;</b></p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<b class="Sy">libfebug.rs</b> allows a programmer to simplify writing
  Rust programs debuggable with <a class="Xr" href="febug.8.html">febug(8)</a> by
  presenting a high-level interface to
  <a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.
<div class="Pp"></div>
There are three compile-time environment variables that allow a programmer to
  customise its behaviour:
<b class="Sy">libfebug.rs</b> allows a programmer to simplify writing Rust
  programs debuggable with <a class="Xr" href="febug.8.html">febug(8)</a> by presenting a high-level
  interface to <a class="Xr" href="febug-abi.5.html">febug-abi(5)</a>.
<p class="Pp">There are three compile-time environment variables that allow a
    programmer to customise its behaviour:</p>
<dl class="Bl-tag">
  <dt></dt>
  <dd><code class="Fd">FEBUG_DONT</code> If set, all functions turn
      into no-ops; this is intended as a way to easily disable
      <a class="Xr" href="febug.8.html">febug(8)</a> integration completely on release
      builds.</dd>
  <dd><code class="Fd">FEBUG_DONT</code> If set, all functions turn into no-ops;
      this is intended as a way to easily disable <a class="Xr" href="febug.8.html">febug(8)</a>
      integration completely on release builds.</dd>
  <dt></dt>
  <dd><code class="Fd">FEBUG_SIGNUM</code> The signal to request from
      <a class="Xr" href="febug.8.html">febug(8)</a> when using


@@ 449,133 433,131 @@ There are three compile-time environment variables that allow a programmer to
      <a class="Xr" href="febug.8.html">febug(8)</a> on. Defaults to
      <span class="Pa">/run/febug.sock</span>.</dd>
</dl>
<div class="Pp"></div>
There are two environment variables that allow a user to customise its
  behaviour:
<p class="Pp">There are two environment variables that allow a user to customise
    its behaviour:</p>
<dl class="Bl-tag">
  <dt><i class="Em">FEBUG_DONT</i></dt>
  <dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so
      all library functions become no-ops.</dd>
  <dd>If set, don't try to connect to <a class="Xr" href="febug.8.html">febug(8)</a>, so all library
      functions become no-ops.</dd>
  <dt><i class="Em">FEBUG_SOCKET</i></dt>
  <dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b>
      to connect to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
  <dd>If set, use its value instead of <b class="Sy">FEBUG_SOCKET</b> to connect
      to <a class="Xr" href="febug.8.html">febug(8)</a></dd>
</dl>
<div class="Pp"></div>
To be debugged, a program needs to, first, call
  <code class="Fn">febug::start_raw</code>() (likely via
  <code class="Fn">febug::start</code>(), which simply passes
  <span class="Pa">b&quot;/run/febug.sock&quot;</span> thereto) to
  connect to <a class="Xr" href="febug.8.html">febug(8)</a>, which, if successful, will
  set <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> to the
  connection's file descriptor.
<div class="Pp"></div>
The program needs to install
  <code class="Fn">febug::debug_handler</code>() (or a wrapper around
  it) as the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (and
  any other signals, if different ones are explicitly requested; if
  <code class="Dv">SIGKILL</code>, some event loop that answers on
  <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> must be in
  place). It's a no-op if
  <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1. This
  finishes set-up. A convenience
  <code class="Fn">febug::install_handler</code>() function is
  provided, doing just that, and returning <b class="Sy">true</b> if
  the handler was installed.
<div class="Pp"></div>
The program should register handlers for types of variables it wishes to handle
  by adding entries to <var class="Vt">febug::FORMATTERS</var>. If no
  handler was registered for a type, or the lock was poisoned,
  <code class="Fn">febug::debug_handler</code>() will write a generic
  &quot;not found&quot; message. The key is
  <b class="Sy">std::any::TypeId</b> corresponding to the debugged
  type; if your type is not not <b class="Sy">'static</b>, 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
  <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.
<div class="Pp"></div>
At any time, when the program wishes to expose a variable, it can construct
  <b class="Sy">febug::Wrapper</b> (likely via one of the convenience
  <b class="Sy">febug::StaticWrappable</b> or
  <b class="Sy">febug::Wrappable</b> traits), which will send a
  <b class="Sy">febug_message</b> with the specified type and signal
  numbers (defaulting to <code class="Li">SIGUSR2 ),</code> ID equal to the
  address of the data argument, and name formatted. It's a no-op if
  <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.
<div class="Pp"></div>
When dropped, <b class="Sy">febug::Wrapper</b> will send a
  <b class="Sy">stop_febug_message</b>. It's a no-op if
  <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.
<div class="Pp"></div>
When it wishes to stop being debugged, the program may call
  <code class="Fn">febug::end</code>() which will shutter and reset
  <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var>, 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.
<p class="Pp">To be debugged, a program needs to, first, call
    <code class="Fn">febug::start_raw</code>() (likely via
    <code class="Fn">febug::start</code>(), which simply passes
    <span class="Pa">b&quot;/run/febug.sock&quot;</span> thereto) to connect to
    <a class="Xr" href="febug.8.html">febug(8)</a>, which, if successful, will set
    <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> to the connection's
    file descriptor.</p>
<p class="Pp">The program needs to install
    <code class="Fn">febug::debug_handler</code>() (or a wrapper around it) as
    the signal handler for <b class="Sy">FEBUG_SIGNUM</b> (and any other
    signals, if different ones are explicitly requested; if
    <code class="Dv">SIGKILL</code>, some event loop that answers on
    <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> must be in place).
    It's a no-op if <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.
    This finishes set-up. A convenience
    <code class="Fn">febug::install_handler</code>() function is provided, doing
    just that, and returning <b class="Sy">true</b> if the handler was
    installed.</p>
<p class="Pp">The program should register handlers for types of variables it
    wishes to handle by adding entries to
    <var class="Vt">febug::FORMATTERS</var>. If no handler was registered for a
    type, or the lock was poisoned,
    <code class="Fn">febug::debug_handler</code>() will write a generic
    &quot;not found&quot; message. The key is <b class="Sy">std::any::TypeId</b>
    corresponding to the debugged type; if your type is not not
    <b class="Sy">'static</b>, 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 <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.</p>
<p class="Pp">At any time, when the program wishes to expose a variable, it can
    construct <b class="Sy">febug::Wrapper</b> (likely via one of the
    convenience <b class="Sy">febug::StaticWrappable</b> or
    <b class="Sy">febug::Wrappable</b> traits), which will send a
    <b class="Sy">febug_message</b> with the specified type and signal numbers
    (defaulting to <code class="Li">SIGUSR2 ),</code> ID equal to the address of
    the data argument, and name formatted. It's a no-op if
    <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.</p>
<p class="Pp">When dropped, <b class="Sy">febug::Wrapper</b> will send a
    <b class="Sy">stop_febug_message</b>. It's a no-op if
    <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var> is -1.</p>
<p class="Pp">When it wishes to stop being debugged, the program may call
    <code class="Fn">febug::end</code>() which will shutter and reset
    <var class="Vt">febug::GLOBAL_CONTROLLED_SOCKET</var>, 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.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
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 <a class="Xr" href="febug.8.html">febug(8)</a> mount:
<div class="Pp"></div>
<div class="Bd Bd-indent">
<pre class="Li">
// 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::&lt;String&gt;(), |of, vid| { 
            let data = unsafe { &amp;*(vid as *const String) }; 
 
            let _ = of.write_all(data.as_bytes()); 
            let _ = of.write_all(b&quot;0); 
        }); 
    } 
 
 
    let threads = (0..10) 
        .map(|i| { 
            thread::spawn(move || { 
                let mut sorteing = &quot;The quick red fox jumps over the lazy brown dog... tHE QUICK RED FOX JUMPS OVER THE LAZY BROWN DOG!!&quot;[0..(i + 1) * 10] 
                    .to_string(); 
                let _sorteing_w = sorteing.wrap(format_args!(&quot;cool_data_{}&quot;, 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::&lt;Vec&lt;_&gt;&gt;(); 
    for t in threads { 
        let _ = t.join(); 
    } 
<div class="Bd Pp Bd-indent">
<pre>
// 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::&lt;String&gt;(), |of, vid| {
            let data = unsafe { &amp;*(vid as *const String) };

            let _ = of.write_all(data.as_bytes());
            let _ = of.write_all(b&quot;0);
        });
    }


    let threads = (0..10)
        .map(|i| {
            thread::spawn(move || {
                let mut sorteing = &quot;The quick red fox jumps over the lazy brown dog... tHE QUICK RED FOX JUMPS OVER THE LAZY BROWN DOG!!&quot;[0..(i + 1) * 10]
                    .to_string();
                let _sorteing_w = sorteing.wrap(format_args!(&quot;cool_data_{}&quot;, 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::&lt;Vec&lt;_&gt;&gt;();
    for t in threads {
        let _ = t.join();
    }
}
</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this
  library.
<div class="Pp"></div>
<a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent C library.
<div class="Pp"></div>
<a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent C++ library.
<a class="Xr" href="febug-abi.5.html">febug-abi(5)</a> &#x2014; the ABI wrapped by this library.
<p class="Pp"><a class="Xr" href="libfebug.3.html">libfebug(3)</a> &#x2014; an equivalent C
  library.</p>
<p class="Pp"><a class="Xr" href="libfebug++.3.html">libfebug++(3)</a> &#x2014; an equivalent C++
    library.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
Written by <span class="An">&#x043D;&#x0430;&#x0431;</span>
  &lt;<a class="Mt" href="mailto:nabijaczleweli@nabijaczleweli.xyz">nabijaczleweli@nabijaczleweli.xyz</a>&gt;
</section>
<section class="Sh">
<h1 class="Sh" id="SPECIAL_THANKS"><a class="permalink" href="#SPECIAL_THANKS">SPECIAL
  THANKS</a></h1>
To all who support further development, in particular:


@@ 583,18 565,20 @@ To all who support further development, in particular:
  <li>ThePhD</li>
  <li>Embark Studios</li>
</ul>
</section>
<section class="Sh">
<h1 class="Sh" id="REPORTING_BUGS"><a class="permalink" href="#REPORTING_BUGS">REPORTING
  BUGS</a></h1>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug
  tracker</a>
<div class="Pp"></div>
febug mailing list:
  &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
  archived at
  <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></div>
<a class="Lk" href="https://todo.sr.ht/~nabijaczleweli/febug">febug tracker</a>
<p class="Pp">febug mailing list:
    &lt;<a class="Mt" href="mailto:~nabijaczleweli/febug@lists.sr.ht">~nabijaczleweli/febug@lists.sr.ht</a>&gt;
    archived at
    <a class="Lk" href="https://lists.sr.ht/~nabijaczleweli/febug">https://lists.sr.ht/~nabijaczleweli/febug</a></p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">January 31, 2021</td>
    <td class="foot-date">March 7, 2021</td>
    <td class="foot-os">Debian</td>
  </tr>
</table>