Status: draft in progress
Overview
This article explains the design of a small RAII wrapper for POSIX file descriptors in C++17.
A file descriptor is only an integer in userspace, but it refers to kernel-managed state. Treating it as a plain integer makes ownership easy to lose track of.
The wrapper is meant to make descriptor ownership explicit and harder to misuse.
Bugs this tries to avoid
The article discusses common descriptor-management bugs:
- leaking descriptors on error paths
- closing the same descriptor twice
- using a descriptor after closing it
- accidentally leaking descriptors across
execve() - corrupting unrelated I/O after descriptor reuse
Design notes
The wrapper is move-only.
Copying is disabled because copying an owning descriptor wrapper would make ownership ambiguous. If a second descriptor is needed, duplication should be explicit.
The article walks through:
- destructor cleanup
- move construction
- move assignment
valid()get()reset()release()- descriptor duplication
swap()
close() behavior
One part of the article focuses on close().
On Linux, retrying close() after EINTR can be wrong because the descriptor number may already have been released and reused.
The article checks this against the Linux file descriptor close path in fs/file.c.
Other choices
The draft also explains:
- why the destructor does not throw
- why
O_CLOEXECis a good default - why construction can return
std::optional - where this wrapper is useful compared with higher-level C++ I/O abstractions
Current status
The wrapper design exists. The article is being polished together with the public repository and examples.