Opening a fifo for writing hangs

Is std buggy, or am I using it wrong?

Example usecase: Let's say I want to open a file for writing, but do some special error behavior if it's a fifo.

The stupid-simple approach would be to use fs::metadata(filename), handle the fifo case separately, and then assume the file is a regular file.
But that creates a TOCTOU bug: After checking the path, the regular file at that path might be swapped with a fifo, and this approach fails.

The "correct" approach would be to somehow use the fstat syscall: Open the file first, then ask the kernel "Hey, this file descriptor I'm holding, is this a fifo?" The point is to ask the question "is fifo?" about the file descriptor (which cannot unexpectedly point to something else) instead of the path-string (which might be volatile).

However, if I try to write this in Rust, I get a chicken-egg problem: open hangs weirdly when encountering a fifo.

Here's example code that demonstrates the issue: Rust Playground

This behavior is the same in Rust 1.70.0 and nightly 2024-03-01.

My question boils down to:

  • Am I using std wrong? How do I correctly open a file?
  • Is this a bug Rust std? I feel like opening should not hang on a fifo, only reading and writing can hang.

That's just how FIFOs work:

The kernel maintains exactly one pipe object for each FIFO
special file that is opened by at least one process. The FIFO
must be opened on both ends (reading and writing) before data can
be passed. Normally, opening the FIFO blocks until the other end
is opened also.