<?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-07-10T11:00:00+00:00</updated>
  <id>https://notes.roscidus.com/</id>
  <author>
    <name>Thomas Leonard</name>
  </author>
  <entry>
    <title type="html">ptys, getaddrinfo, chown</title>
    <link href="https://notes.roscidus.com/2026/07/10/"></link>
    <updated>2026-07-10T11:00:00+00:00</updated>
    <id>https://notes.roscidus.com/2026/07/10</id>
    <content type="html"><![CDATA[<p>I've been continuing to fix issues and review PRs on Eio and uring.</p>
<h2 id="eio-and-uring">Eio and uring</h2>
<p>I reviewed and merged Anil's pseudoterminal support PR (started in 2023!),
which allows running a subprocess with a virtual terminal, controlled by the parent:</p>
<ul>
<li>Support for creating ptys and a login_tty fork_action <a href="https://github.com/ocaml-multicore/eio/pull/531">#531</a>.
</li>
</ul>
<p>The main issue here was making it work in harmony with Eio's <code>inherit_fds</code> feature.</p>
<p>I reviewed and merged <code>chown</code> support (similar to the <code>chmod</code> support added last time).</p>
<ul>
<li>Support <code>chown</code> in eio_posix and eio_linux <a href="https://github.com/ocaml-multicore/eio/pull/781">#781</a>.
</li>
</ul>
<p>I failed to spot some important problems with the new code,
but luckily Anil noticed them soon after the merge:</p>
<ul>
<li>Use the right flags for chown and add a linux/other test <a href="https://github.com/ocaml-multicore/eio/pull/864">#864</a>.
</li>
<li>chmod: prevent sandbox escape using symlinks <a href="https://github.com/ocaml-multicore/eio/pull/872">#872</a>.
</li>
<li>chown: prevent sandbox escape using symlinks <a href="https://github.com/ocaml-multicore/eio/pull/877">#877</a>.
</li>
</ul>
<p>OCaml's <code>Unix.getaddrinfo</code> returns <code>[]</code> (no results) on any error, which can be confusing as it hides the real error.
For example, you can be told that a name doesn't exist when in fact the process has just reached its limit on the number of open FDs!
I updated an old PR from Christiano which raises a suitable exception instead (the problem with the old PR was that it was based on OCaml's code, but the OCaml developers weren't willing to let us use it so it needed to be reimplemented):</p>
<ul>
<li>Report errors from getaddrinfo <a href="https://github.com/ocaml-multicore/eio/pull/866">#866</a>.
</li>
</ul>
<p>Disappointingly, it turned out that the underlying <code>getaddrinfo</code> implementation in glibc also
<a href="https://github.com/ocaml-multicore/eio/issues/776#issuecomment-4893969086">fails</a> to propagate the FDs-limit error!</p>
<p>I updated Eio to use the safer <code>Res.t</code> result type we recently added to uring:</p>
<ul>
<li>eio_linux: use <code>Uring.Res</code> module for safer error handling <a href="https://github.com/ocaml-multicore/eio/pull/868">#868</a>.
</li>
</ul>
<p>We had some discussion about whether the code for reading string-valued socket options was correct,
and made the code a bit stricter:</p>
<ul>
<li>Be more careful about unterminated string socket options <a href="https://github.com/ocaml-multicore/eio/pull/876">#876</a>.
</li>
</ul>
<p><code>Path.load</code> didn't work correctly with files in <code>/proc</code>, which report a size of 0 but do have content.
Worked with Patrick to get that fixed:</p>
<ul>
<li>Allow <code>Eio.Path.load</code> to handle files with zero size <a href="https://github.com/ocaml-multicore/eio/pull/869">#869</a>.
</li>
</ul>
<p>It turns out that you also have to be careful about buffer sizes when reading from <code>/proc</code>,
as Linux can give incorrect results for small buffers:</p>
<ul>
<li>Use a sensible minimum buffer size for <code>Path.load</code> <a href="https://github.com/ocaml-multicore/eio/pull/878">#878</a>.
</li>
</ul>
<p>I learnt about Linux's <a href="https://docs.kernel.org/accounting/psi.html">/proc/pressure/io</a> system,
and investigated a report that Eio was causing excessive pressure
(it turned out to be a known problem in Linux with uring):</p>
<ul>
<li>High iowait/IO pressure reported for an idle Eio io_uring service <a href="https://github.com/ocaml-multicore/eio/issues/862">#862</a>.
</li>
</ul>
<p>Other minor PR reviews:</p>
<ul>
<li>eio_windows: fix removing of FDs from read/write sets <a href="https://github.com/ocaml-multicore/eio/pull/861">#861</a>.
</li>
<li>Switch fstat to statx on linux and fetch blksize <a href="https://github.com/ocaml-multicore/eio/pull/865">#865</a>.
</li>
<li>fork_action: retry on eintr when writing to pipe <a href="https://github.com/ocaml-multicore/eio/pull/870">#870</a>.
</li>
<li>eio_linux: these read/write functions didn't hold the fd open <a href="https://github.com/ocaml-multicore/eio/pull/871">#871</a>.
</li>
<li>eio_posix, eio_windows: map ENOPROTOOPT to Invalid_option <a href="https://github.com/ocaml-multicore/eio/pull/874">#874</a>.
</li>
<li>Add bindings for vectored read/writev fixed buffers <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/155">#155</a>.
</li>
<li>Update to liburing.2.15 <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/157">#157</a>.
</li>
<li>uring: update min to 2.15.0+ so we can use new functionality <a href="https://github.com/ocaml-multicore/eio/pull/867">#867</a>.
</li>
</ul>
<h2 id="prometheus">Prometheus</h2>
<p>I also made a few minor cleanups in mirage/prometheus:</p>
<p>Thomas Gazagnaire noticed that it was formatting floats with <code>%f</code>, losing some precision:</p>
<ul>
<li>Format floats with <code>%.17g</code> <a href="https://github.com/mirage/prometheus/pull/62">#62</a>.
</li>
</ul>
<p>Prometheus also had some dependencies that aren't needed with modern compiler versions:</p>
<ul>
<li>Remove Astring dependency <a href="https://github.com/mirage/prometheus/pull/63">#63</a>.
</li>
<li>Remove dependency on Asetmap <a href="https://github.com/mirage/prometheus/pull/64">#64</a>.
</li>
</ul>
<p>At some point Prometheus needs some larger refactoring, to split off the Lwt parts from the core.</p>
]]></content>
  </entry>
  <entry>
    <title type="html">off-site, socket options, fifos</title>
    <link href="https://notes.roscidus.com/2026/06/26/"></link>
    <updated>2026-06-26T10:00:00+00:00</updated>
    <id>https://notes.roscidus.com/2026/06/26</id>
    <content type="html"><![CDATA[<p>I spent a few pleasant days meeting people at the Tarides off-site near Paris.
Apart from that, I've been continuing to review and finish Eio PRs.</p>
<h2 id="eio">Eio</h2>
<p>We've wanted support for setting socket options in Eio for ages,
and I finally got around to reviewing Anil's PR adding them.
It was pretty big, so I split parts of it off into two smaller PRs
and reviewed them separately (it's all merged now):</p>
<ul>
<li>Initial support for setting/getting socket options <a href="https://github.com/ocaml-multicore/eio/pull/858">#858</a>.
</li>
<li>Add portable names for common network options <a href="https://github.com/ocaml-multicore/eio/pull/859">#859</a>.
</li>
<li>eio_linux: Add Linux-specific socket options <a href="https://github.com/ocaml-multicore/eio/pull/575#issuecomment-4791441131">#575</a>.
</li>
</ul>
<p><a href="https://github.com/talex5/wayland-proxy-virtwl">wayland-proxy-virtwl</a> uses a FIFO (named piped) to accept debug commands
(asking it to dump the log ring to a file).
I'd noticed a while ago that it would spin using 100% CPU when run with <code>EIO_BACKEND=posix</code>
and finally got around to investigating:</p>
<ul>
<li>eio_posix: fifos don't work properly <a href="https://github.com/ocaml-multicore/eio/issues/856">#856</a>.
</li>
</ul>
<p>In summary, opening a FIFO for reading normally waits for a writer to connect,
but in a concurrent application that would stop the whole program.
To fix that, we open them in non-blocking mode.
But that has a wierd behaviour: trying to read from the pipe immediately returns end-of-file
rather than <code>EAGAIN</code>, even though <code>select</code> says that it's not ready!</p>
<ul>
<li>eio_posix: wait for a writer when first reading from a FIFO <a href="https://github.com/ocaml-multicore/eio/pull/857">#857</a>.
</li>
</ul>
<p>Other reviewed PRs:</p>
<ul>
<li>
<p>Propagate <code>errno</code> back from <code>fork_actions</code> into <code>Eio.Process</code> <a href="https://github.com/ocaml-multicore/eio/pull/854#pullrequestreview-4498270876">#854</a>.<br />
This allows handling specific errors, rather than just getting a generic <code>Failure</code> with a string.</p>
</li>
<li>
<p>Support <code>chmod</code> in Eio_linux and Eio_posix <a href="https://github.com/ocaml-multicore/eio/pull/785#pullrequestreview-4526775944">#785</a>.<br />
Another of Patrick's PRs adding missing Unix functionality to Eio.</p>
</li>
<li>
<p>Relax return types of <code>Eio.Process.Pipe</code> <a href="https://github.com/ocaml-multicore/eio/pull/775#pullrequestreview-4572672934">#775</a>.<br />
This was an Outreachy PR that got abandoned in 2024; finishing it off was a quick job.</p>
</li>
</ul>
<h2 id="dune-pkg">dune pkg</h2>
<p>Talking with Shon Feder at the Tarides off-site reminded me I should try out
<a href="https://dune.readthedocs.io/en/latest/tutorials/dune-package-management/index.html">OCaml Package Management With Dune</a>.
To build an OCaml program you normally first run <code>opam install --deps-only -t .</code> to get the dependencies
and then <code>dune build</code> to build it, but you can have dune get the required packages too by using <code>dune build --pkg=enable</code>.
It's still experimental, but looks promising. Some things I noticed:</p>
<ul>
<li>
<p>Dune's progress indicator isn't really designed for long build times, such as downloading and building the OCaml compiler.
It could do with showing more information.</p>
</li>
<li>
<p>It doesn't seem to support installing depexts (non-OCaml dependencies) yet, although it can tell you what they are.</p>
</li>
<li>
<p>But default it doesn't use a shared cache, so if you build two projects this way it will build the compiler twice.
You need to set <code>DUNE_CACHE=enabled</code> to turn that on.</p>
</li>
</ul>
<p>I'm using it now to generate this blog, and that's working nicely.
I also tried it with Eio, but hit a problem trying to generate the docs:</p>
<ul>
<li>Internal error with <code>dune build --pkg=enable @doc-new</code> <a href="https://github.com/ocaml/dune/issues/15290">#15290</a>.
</li>
</ul>
]]></content>
  </entry>
  <entry>
    <title type="html">eio and uring PR reviews</title>
    <link href="https://notes.roscidus.com/2026/06/12/"></link>
    <updated>2026-06-12T13:00:00+00:00</updated>
    <id>https://notes.roscidus.com/2026/06/12</id>
    <content type="html"><![CDATA[<p>I've mostly just been reviewing and finishing PRs recently.</p>
<h2 id="eio">Eio</h2>
<p>I took Patrick's PR for improved directory reading and finished it off.
As well as providing incremental reads, this PR also gives you the entry's type with the name,
which is much faster than calling <code>stat</code> on each one.
I improved the performance of the <code>eio_posix</code> version and tidied things up a bit:</p>
<ul>
<li>Incremental directory reading <a href="https://github.com/ocaml-multicore/eio/pull/821#issuecomment-4679882373">#821</a>.
</li>
</ul>
<p>After reviewing Anil's changes to <code>Uring.Region.init</code>
(<a href="https://github.com/ocaml-multicore/ocaml-uring/pull/145">#145</a>),
we realised that it would be cleaner to move fixed-buffer regions to Eio:</p>
<ul>
<li>Add <code>Eio_linux.Low_level.Fixed</code> <a href="https://github.com/ocaml-multicore/eio/pull/848">#848</a>.
</li>
</ul>
<p>Reviewing Anil's uring PR adding Linux specific errnos
(<a href="https://github.com/ocaml-multicore/ocaml-uring/pull/152">#152</a>),
I realised that the code using them is probably unnecessary anyway and got rid of it:</p>
<ul>
<li>eio_linux: remove unused code <a href="https://github.com/ocaml-multicore/eio/pull/851">#851</a>.
</li>
</ul>
<p>I've found Eio's <code>Path.open_dir</code> function is confusingly named.
It's not about opening directories (that's just an implementation detail),
it's about restricting a path to a subtree.
I proposed a PR to rename it (discussion is on-going):</p>
<ul>
<li>Rename <code>Path.open_dir</code> to <code>open_subtree</code> <a href="https://github.com/ocaml-multicore/eio/pull/853">#853</a>.
</li>
</ul>
<p>I'm still intending to revive Anil's socket options PR (<a href="https://github.com/ocaml-multicore/eio/pull/575">#575</a>),
but as a first step I sorted out an encoding issue that was
preventing the tests diff from being shown:</p>
<ul>
<li>Improve formatting of IP addresses in tests <a href="https://github.com/ocaml-multicore/eio/pull/847">#847</a>.
</li>
</ul>
<p>Since Eio's very first Git commit,
the scheduler has been special-casing fixed-buffer IO operations.
Moving it out simplified things nicely:</p>
<ul>
<li>eio_linux: move read/write retries out of scheduler <a href="https://github.com/ocaml-multicore/eio/pull/849">#849</a>.
</li>
</ul>
<p>The <code>lintcstubs-arity</code> package auto-generates C function declarations from OCaml code,
which avoids some common mistakes (like returning <code>void</code> instead of a <code>value</code> of <code>Val_unit</code>,
which has caused unpredictable segfaults in the past).
The package was previously only used if installed for some reason, so people often forget to run it:</p>
<ul>
<li>Add lintcstubs-arity as a test dependency <a href="https://github.com/ocaml-multicore/eio/pull/846">#846</a>.
</li>
</ul>
<p>It would be good to get the whole of <a href="https://github.com/edwintorok/lintcstubs">lintcstubs</a>
working one day (currently it only works with old versions of OCaml).</p>
<h2 id="other-pr-reviews">Other PR reviews</h2>
<ul>
<li>
<p>Statx attribute supported check was inverted <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/142#pullrequestreview-4399937750">#142</a>.<br />
Which led us to revise the API for <code>Attr.check</code>.</p>
</li>
<li>
<p>Add <code>shutdown</code>, <code>socket</code>, <code>renameat</code> and <code>symlinkat</code> <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/147#pullrequestreview-4408580318">#147</a>.</p>
</li>
<li>
<p>Fix debug messages in <code>ocaml_uring_unregister_buffers</code> <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/146#pullrequestreview-4410313082">#146</a>.</p>
</li>
<li>
<p><code>caml_uring_wait_cqe</code> should have the same null cqe check that the timeout variant has <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/148">#148</a>.</p>
</li>
<li>
<p>Add fallocate and ftruncate bindings <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/149#pullrequestreview-4428414729">#149</a>.</p>
</li>
<li>
<p>Allow setting socket flags on socket creation <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/151#pullrequestreview-4437540864">#151</a>.</p>
</li>
</ul>
]]></content>
  </entry>
  <entry>
    <title type="html">uring, eio, mdx, tar-eio</title>
    <link href="https://notes.roscidus.com/2026/06/01/"></link>
    <updated>2026-06-01T09:00:00+00:00</updated>
    <id>https://notes.roscidus.com/2026/06/01</id>
    <content type="html"><![CDATA[<h2 id="uring">Uring</h2>
<p>I released uring 2.14.0 with the recent changes:</p>
<ul>
<li>Prepare release <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/140">#140</a>.
</li>
<li>[new release] uring (2.14.0) <a href="https://github.com/ocaml/opam-repository/pull/29954">#29954</a>.
</li>
</ul>
<p>I also continued looking at using uring flags for better Eio performance.
First, Eio now tells uring that each ring has a single submitting thread:</p>
<ul>
<li>eio_linux: use <code>IORING_SETUP_SINGLE_ISSUER</code> <a href="https://github.com/ocaml-multicore/eio/pull/841">#841</a>.
</li>
</ul>
<p>This allows uring to skip some locking apparently, but it didn't make any noticable difference to me.
However, it does mean you get a better error if you accidentally try to submit from two threads,
which can happen if something calls <code>Unix.fork</code> (<a href="https://github.com/ocaml-multicore/eio/issues/801">eio/issues/801</a>).
Except that <code>Uring.submit</code> failed to report errors:</p>
<ul>
<li>Report errors from io_uring_submit <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/144">#144</a>.
</li>
</ul>
<p>Last week I tried using <code>IORING_SETUP_COOP_TASKRUN</code> and <code>IORING_SETUP_DEFER_TASKRUN</code>,
but noted that <code>DEFER</code> caused a test to hang.
The test has a fiber that's always runnable (and keeps yielding) and is checking that IO still gets handled.
With <code>DEFER</code>, Eio sees that there are no completions ready and so just gets on with the CPU-intensive fiber.
I didn't see this problem with <code>COOP</code> mode, but I'm not sure why not because we're not doing any syscalls.</p>
<p>In any case, the fix turned out to be simple: uring has a <code>IORING_SETUP_TASKRUN_FLAG</code> which tells the kernel
to set a flag in the shared memory if there are completion tasks that need to run,
and <code>io_uring_peek_cqe</code> checks this flag and enters the kernel automatically if needed.
So, Eio is now using <code>DEFER</code> mode:</p>
<ul>
<li>eio_linux: use &quot;IORING_SETUP_DEFER_TASKRUN&quot; for performance <a href="https://github.com/ocaml-multicore/eio/pull/842">#842</a>.
</li>
</ul>
<p>I'd be interested to know if anyone else sees a speed-up with this.</p>
<p>According to <code>io_uring_setup_flags(7)</code>, zero-copy receive and ring resizing also require <code>DEFER</code> mode.</p>
<h2 id="pr-reviews">PR reviews</h2>
<p>I reviewed some more PRs (from Patrick, Anil and Mark):</p>
<ul>
<li>
<p>COMMENTED Incremental directory reading <a href="https://github.com/ocaml-multicore/eio/pull/821#pullrequestreview-4380314629">#821</a>.<br />
Greatly improves the speed of scanning directories by returning the type of each entry as part of the read
(saving one stat per file) and by allowing you to process the listing incrementally.</p>
</li>
<li>
<p>Support <code>chown</code> in <code>eio_posix</code> and <code>eio_linux</code> <a href="https://github.com/ocaml-multicore/eio/pull/781#pullrequestreview-4388951883">#781</a>.</p>
</li>
<li>
<p>docker: add <code>?os</code> to Peek and Pull (default linux) <a href="https://github.com/ocurrent/ocurrent/pull/472#pullrequestreview-4381911366">#472</a>.</p>
</li>
<li>
<p>Statx attribute supported check was inverted <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/142#pullrequestreview-4389540391">#142</a>.<br />
<code>Uring.Statx.Attr.check</code> had a logic error, but now I'm wondering if it's even useful.</p>
</li>
<li>
<p>Fix <code>dio_offset_align</code> statx getter returning wrong field <a href="https://github.com/ocaml-multicore/ocaml-uring/pull/141#pullrequestreview-4388906740">#141</a>.</p>
</li>
</ul>
<h2 id="mdx">MDX</h2>
<p>I updated my MDX hang-detector (<a href="https://github.com/realworldocaml/mdx/pull/476">#476</a>) to report accurate locations for cram tests too.
The CI was failing, which turned out to be due to a recent change in dune:</p>
<ul>
<li>MDX CI is failing <a href="https://github.com/realworldocaml/mdx/issues/477">#477</a>.
</li>
</ul>
<h2 id="minor-prs">Minor PRs</h2>
<p>I updated uring to use <code>MSG_CMSG_CLOEXEC</code> when receiving file descriptors,
and this week I made the equivalent change in <code>eio_posix</code> (for other systems):</p>
<ul>
<li>eio_posix: use <code>MSG_CMSG_CLOEXEC</code> when receiving file descriptors <a href="https://github.com/ocaml-multicore/eio/pull/843">#843</a>.
</li>
</ul>
<p>Disappointingly, it turns out that macos doesn't support this flag and I had to add a work-around for that.</p>
<p>The Eio benchmarks use a Dockerfile for the tests and it hadn't been updated for ages.
I was hoping that using newer dependencies might show a speed improvement, but it didn't help:</p>
<ul>
<li>Update Dockerfiles to recent versions <a href="https://github.com/ocaml-multicore/eio/pull/844">#844</a>.
</li>
</ul>
<h2 id="tar-eio">tar-eio</h2>
<p>I had a brief look at improving the <a href="https://github.com/mirage/ocaml-tar/blob/main/eio/tar_eio.mli">eio-tar API</a>,
which has a number of problems currently:</p>
<ul>
<li>It requires the source tar file to be opened in read/write mode, even for extracting.
</li>
<li>It exposes the confusing <code>Tar.t</code> type that's used by the core to abstract over monads and effects,
which Eio users shouldn't need to care about.
</li>
<li>As a consequence, <code>Tar_eio.extract</code> needs to take a switch argument because it doesn't actually do the extraction,
but just returns a computation that runs later, and so needs to hold on to the argument.
</li>
</ul>
<p>Patrick explained to me that <code>extract</code> needs to return a computation so that you can wrap it with <code>Tar_gz.in_gzipped</code>.
I think it would make a lot more sense to wrap the source file with a gzip decoder, rather than wrap the computation,
but changing it all looked like a fair bit of work and I didn't go any further.</p>
]]></content>
  </entry>
  <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>
