mirror of
https://github.com/troglobit/finit.git
synced 2026-09-30 13:02:37 +07:00
A call is parked until the resolver says who sent it, and an outbound call sits in a pending slot until its reply lands. Neither had a way to give up. A broker that answers GetConnectionUnixUser slowly, or not at all, leaves the caller waiting forever and keeps the slot; four of those and every later privileged call is refused with LimitsExceeded until Finit restarts. libink cannot time itself out, it has no event loop, so the deadline is the embedder's to keep. One sweep per connection covers both, and the ordering between them stays in the library rather than in each embedder: calls first, because one timing out usually resolves the park it was made for, and AccessDenied tells that caller more than a bare timeout. The sweep is armed when a resolve is deferred and stops rearming as soon as nothing is outstanding, so a system that never meets a broker never wakes up for it. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
69 lines
1.3 KiB
C
69 lines
1.3 KiB
C
/* libink — shared I/O helpers.
|
|
*
|
|
* Server send paths (libink/dispatch.c, libink/auth.c) and the
|
|
* client (libink/client.c) all need EINTR-resilient write_all /
|
|
* read_full. On any other error they return -1 with an unknown
|
|
* number of bytes already transferred.
|
|
*
|
|
* Also the clock the expiry sweeps measure against: monotonic, so a
|
|
* step in wall time cannot make a call look older or younger than it
|
|
* is.
|
|
*
|
|
* Copyright (c) 2026 Joachim Wiberg <troglobit@gmail.com>
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "internal.h"
|
|
|
|
uint64_t __now_ms(void)
|
|
{
|
|
struct timespec ts;
|
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &ts))
|
|
return 0;
|
|
|
|
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)(ts.tv_nsec / 1000000);
|
|
}
|
|
|
|
int __io_write_all(int fd, const void *buf, size_t len)
|
|
{
|
|
const char *p = buf;
|
|
|
|
while (len > 0) {
|
|
ssize_t n = write(fd, p, len);
|
|
|
|
if (n < 0) {
|
|
if (errno == EINTR)
|
|
continue;
|
|
return -1;
|
|
}
|
|
p += n;
|
|
len -= (size_t)n;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int __io_read_full(int fd, void *buf, size_t len)
|
|
{
|
|
char *p = buf;
|
|
|
|
while (len > 0) {
|
|
ssize_t n = read(fd, p, len);
|
|
|
|
if (n == 0)
|
|
return -1;
|
|
if (n < 0) {
|
|
if (errno == EINTR)
|
|
continue;
|
|
return -1;
|
|
}
|
|
p += n;
|
|
len -= (size_t)n;
|
|
}
|
|
return 0;
|
|
}
|