<?xml version="1.0" encoding="UTF-8"?>

<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://notes.roscidus.com/">
  <title>Thomas Leonard's work notes</title>
  <link href="https://notes.roscidus.com/atom.xml" rel="self"></link>
  <link href="https://notes.roscidus.com/"></link>
  <updated>2026-05-24T09:00:00+00:00</updated>
  <id>https://notes.roscidus.com/</id>
  <author>
    <name>Thomas Leonard</name>
  </author>
  <entry>
    <title type="html">new contract, uring, eio, mdx</title>
    <link href="https://notes.roscidus.com/2026/05/24/"></link>
    <updated>2026-05-24T09:00:00+00:00</updated>
    <id>https://notes.roscidus.com/2026/05/24</id>
    <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>I've got a new contract to do some Eio maintenance and related work for 3 months,
and I intend to post rough notes about what I'm working on here.</p>
<h2 id="unix-fds">Unix FDs</h2>
<p>I've been having a look at the backlog of PRs for ocaml-uring.
<a href="https://github.com/ocaml-multicore/ocaml-uring/pull/129">ocaml-uring#129</a> and
<a href="https://github.com/ocaml-multicore/ocaml-uring/pull/130">ocaml-uring#130</a>
were two different attempts at dealing with file descriptors
(working around OCaml's lack of a safe way to convert between <code>int</code>
and <code>Unix.file_descr</code>).
After trying the proposed API out with Eio,
I went with a modified version of #129:</p>
<ul>
<li>Add <code>Uring.Res</code> module to handle result values <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/131">#131</a>.
</li>
</ul>
<p>Ideally, Eio would use the new features to handle results more safely,
but until the new version is released I just added a cast so that Eio
will work with either version:</p>
<ul>
<li>Update for new <code>Uring.Res</code> API <a href="https://github.com/ocaml-multicore/eio/pull/839">#839</a>.
</li>
</ul>
<h2 id="detecting-hangs-in-mdx-tests">Detecting hangs in MDX tests</h2>
<p>MDX reads a markdown document and runs all the examples in it,
checking that they give the expected result.
However, if a test hangs then MDX doesn't tell you where the problem was,
and if a test hangs in CI then you just get a message at the end of an hour
saying that the tests timed out, which was making it difficult to find out why
the uring tests were hanging on riscv.</p>
<p>I made a PR to MDX that shows the current test location on Ctrl-C,
and also prints warning messages if a test is taking a long time:</p>
<ul>
<li>Report location of hangs <a href="https://github.com/realworldocaml/mdx/pull/476">#476</a>.
</li>
</ul>
<p>Unfortunately, it doesn't work very well when used with dune yet
(dune uses SIGKILL to terminate MDX, and hides output until the whole file completes by default).</p>
<p>The riscv hang turned out to be because the CI machines are running a very old version of Linux.
The tests tried to write a byte to a pipe using uring and then read it back.
The write failed because Linux was too old to support that API, but MDX continued anyway with the read.</p>
<ul>
<li>If the sending test fails, don't wait to receive <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/134">#134</a>.
</li>
</ul>
<h2 id="updated-uring-to-2140">Updated uring to 2.14.0</h2>
<p>The main problem here was getting the new C header file in the right place.
The existing build process ended up with 4 copies of each header, which was pretty confusing.
I simplified it a bit and documented the rest:</p>
<ul>
<li>Document and simplify the build process <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/137">#137</a>.
</li>
<li>Update to uring 2.14 <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/138">#138</a>.
</li>
</ul>
<h2 id="improve-uring-performance-in-eio">Improve uring performance in Eio</h2>
<p>I tried using various flags to tell uring that it doesn't need to interrupt us whenever a completion is due,
as we have an event loop and will check soon anyway:</p>
<ul>
<li>eio_linux: use newer uring flags for performance <a href="https://github.com/ocaml-multicore/eio/pull/840">#840</a>.
</li>
</ul>
<p>Using <code>IORING_SETUP_COOP_TASKRUN</code> led to a big speed up on my machine for the HTTP tests
(from about 350k requests per second to 450k!).
However, it seemed to have no noticable effect on the CI benchmark machine.</p>
<p>Using <code>IORING_SETUP_DEFER_TASKRUN</code> had a similar effect, but caused one of the tests to hang
(my MDX hang-detector came in handy here!).
The problem is that if there are no pending completions from the kernel, but we
do have other work to do, then we do that first, but then we never enter the kernel
and the completions are never written.
Would probably be easy enough to change the scheduler to enter the kernel anyway
from time to time.</p>
<h2 id="various-minor-fixes">Various minor fixes</h2>
<ul>
<li>Use <code>MSG_CMSG_CLOEXEC</code> when receiving file descriptors <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/132">#132</a>.
</li>
<li>Warn about ZFS bug when using <code>write_fixed</code> <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/133">#133</a>.
</li>
</ul>
<p>Reviewed and merged various PRs:</p>
<ul>
<li>Register <code>polling_timeout</code> with GC in <code>ocaml_uring_setup</code> <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/136">#136</a>.
</li>
<li>Simplify custom &quot;env&quot; type in example <a href="https://github.com/ocaml-multicore/eio/pull/832#pullrequestreview-4264749262">#832</a>.
</li>
<li>Add <code>Eio_unix.Stdenv.override</code> for updating environments <a href="https://github.com/ocaml-multicore/eio/pull/823">#823</a>.
</li>
<li>Add <code>send_zc</code> and <code>sendmsg_zc</code> ops <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/139">#139</a>.
</li>
</ul>
<h2 id="ocaml-tar-bug">ocaml-tar bug</h2>
<p>An <a href="https://github.com/mirage/ocaml-tar/pull/177/changes/51ceb0a15982993503c169b9d84456fd50eabe99">ocaml-tar bug</a> was found
that could cause it to write files outside of the target directory.
Anil Madhavapeddy made a quick fix for the <code>tar-eio</code> package and I reviewed it
(though I'm unfamiliar with <code>tar-eio</code>).</p>
<p>Interestingly, while the <code>tar-unix</code> and <code>tar-lwt-unix</code> versions are always vulnerable,
the unpatched version is not necessarily unsafe with <code>tar-eio</code>.
This is because <code>tar-eio</code> gets its ability to write files from its caller.
If the caller only gives it access to the output directory then the bug cannot be exploited.</p>
<p>However, you can forget to do that, so ensuring <code>tar-eio</code> does it in all cases is still a good idea.</p>
<h2 id="set-up-work-log">Set up work log</h2>
<p>I needed something simple to publish these work updates,
without polluting my main blog, so I set up this sub-site for it.
I copied the OCaml static site generator I wrote for the <a href="https://roscidus.com/blog/">main blog</a>
and simplified it for this one.</p>
]]></content>
  </entry>
</feed>
