Fix EINTR handling

This commit is contained in:
2025-08-23 17:28:34 -04:00
parent 5b4a28a8ca
commit a820efa2e6
6 changed files with 131 additions and 24 deletions

View File

@@ -329,6 +329,41 @@ static_assert(std::is_trivially_destructible_v<T>, "Arena requires trivially des
// assert(file_exists(path)); // File might legitimately not exist - use return code instead
```
### System Call Error Handling
When a system call is interrupted by a signal (`EINTR`), it is usually necessary to retry the call. This is especially true for "slow" system calls that can block for a long time, such as `read`, `write`, `accept`, `connect`, `close`, `sem_wait`, and `epoll_wait`.
**Rule:** Always wrap potentially interruptible system calls in a `do-while` loop that checks for `EINTR`.
**Example:**
```cpp
int fd;
do {
fd = accept(listen_fd, nullptr, nullptr);
} while (fd == -1 && errno == EINTR);
if (fd == -1) {
// Handle other errors
perror("accept");
abort();
}
```
**Non-interruptible calls:**
Most system calls are not interruptible in practice. For these, it is not necessary to add a retry loop. This includes:
* `fcntl` (with `F_GETFL`, `F_SETFL`, `F_GETFD`, `F_SETFD` - note: `F_SETLKW` and `F_OFD_SETLKW` CAN return EINTR)
* `epoll_ctl`
* `socketpair`
* `pipe`
* `setsockopt`
* `epoll_create1`
When in doubt, consult the `man` page for the specific system call to see if it can return `EINTR`.
---
## Documentation