Fix EINTR handling
This commit is contained in:
35
style.md
35
style.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user