24 #include <seastar/core/sstring.hh>
25 #include "abort_on_ebadf.hh"
26 #include <sys/types.h>
32 #include <sys/ioctl.h>
33 #include <sys/eventfd.h>
34 #include <sys/timerfd.h>
35 #include <sys/socket.h>
36 #include <sys/epoll.h>
39 #include <system_error>
46 #include <seastar/net/socket_defs.hh>
47 #include <seastar/util/std-compat.hh>
60 inline void throw_system_error_on(
bool condition,
const char* what_arg =
"");
63 inline void throw_kernel_error(T r);
67 void operator()(
void* ptr)
const;
70 using mmap_area = std::unique_ptr<char[], mmap_deleter>;
72 mmap_area mmap_anonymous(
void* addr,
size_t length,
int prot,
int flags);
80 ~
file_desc() {
if (_fd != -1) { ::close(_fd); } }
81 void operator=(
const file_desc&) =
delete;
84 std::swap(_fd, x._fd);
93 auto r = ::close(_fd);
94 throw_system_error_on(r == -1,
"close");
97 int get()
const {
return _fd; }
103 static file_desc open(sstring name,
int flags, mode_t mode = 0) {
104 int fd = ::open(name.c_str(), flags, mode);
105 throw_system_error_on(fd == -1,
"open");
109 int fd =
::socket(family, type, protocol);
110 throw_system_error_on(fd == -1,
"socket");
113 static file_desc eventfd(
unsigned initval,
int flags) {
114 int fd = ::eventfd(initval, flags);
115 throw_system_error_on(fd == -1,
"eventfd");
118 static file_desc epoll_create(
int flags = 0) {
119 int fd = ::epoll_create1(flags);
120 throw_system_error_on(fd == -1,
"epoll_create1");
123 static file_desc timerfd_create(
int clockid,
int flags) {
124 int fd = ::timerfd_create(clockid, flags);
125 throw_system_error_on(fd == -1,
"timerfd_create");
128 static file_desc temporary(sstring directory);
130 int fd = ::dup(get());
131 throw_system_error_on(fd == -1,
"dup");
135 auto ret = ::accept4(_fd, &sa.as_posix_sockaddr(), &sa.addr_length, flags);
136 throw_system_error_on(ret == -1,
"accept4");
139 static file_desc inotify_init(
int flags);
141 std::optional<file_desc> try_accept(
socket_address& sa,
int flags = 0) {
142 auto ret = ::accept4(_fd, &sa.as_posix_sockaddr(), &sa.addr_length, flags);
143 if (ret == -1 && errno == EAGAIN) {
146 throw_system_error_on(ret == -1,
"accept4");
149 void shutdown(
int how) {
150 auto ret = ::shutdown(_fd, how);
151 if (ret == -1 && errno != ENOTCONN) {
152 throw_system_error_on(ret == -1,
"shutdown");
155 void truncate(
size_t size) {
156 auto ret = ::ftruncate(_fd, size);
157 throw_system_error_on(ret,
"ftruncate");
159 int ioctl(
int request) {
160 return ioctl(request, 0);
162 int ioctl(
int request,
int value) {
163 int r = ::ioctl(_fd, request, value);
164 throw_system_error_on(r == -1,
"ioctl");
167 int ioctl(
int request,
unsigned int value) {
168 int r = ::ioctl(_fd, request, value);
169 throw_system_error_on(r == -1,
"ioctl");
173 int ioctl(
int request, X& data) {
174 int r = ::ioctl(_fd, request, &data);
175 throw_system_error_on(r == -1,
"ioctl");
179 int ioctl(
int request, X&& data) {
180 int r = ::ioctl(_fd, request, &data);
181 throw_system_error_on(r == -1,
"ioctl");
185 int setsockopt(
int level,
int optname, X&& data) {
186 int r = ::setsockopt(_fd, level, optname, &data,
sizeof(data));
187 throw_system_error_on(r == -1,
"setsockopt");
190 int setsockopt(
int level,
int optname,
const char* data) {
191 int r = ::setsockopt(_fd, level, optname, data, strlen(data) + 1);
192 throw_system_error_on(r == -1,
"setsockopt");
195 int setsockopt(
int level,
int optname,
const void* data, socklen_t len) {
196 int r = ::setsockopt(_fd, level, optname, data, len);
197 throw_system_error_on(r == -1,
"setsockopt");
200 template <
typename Data>
201 Data getsockopt(
int level,
int optname) {
203 socklen_t len =
sizeof(data);
204 memset(&data, 0, len);
205 int r = ::getsockopt(_fd, level, optname, &data, &len);
206 throw_system_error_on(r == -1,
"getsockopt");
209 int getsockopt(
int level,
int optname,
char* data, socklen_t len) {
210 int r = ::getsockopt(_fd, level, optname, data, &len);
211 throw_system_error_on(r == -1,
"getsockopt");
216 auto r = ::fstat(_fd, &buf);
217 throw_system_error_on(r == -1,
"fstat");
220 std::optional<size_t> read(
void* buffer,
size_t len) {
221 auto r = ::read(_fd, buffer, len);
222 if (r == -1 && errno == EAGAIN) {
225 throw_system_error_on(r == -1,
"read");
226 return { size_t(r) };
228 std::optional<ssize_t> recv(
void* buffer,
size_t len,
int flags) {
229 auto r = ::recv(_fd, buffer, len, flags);
230 if (r == -1 && errno == EAGAIN) {
233 throw_system_error_on(r == -1,
"recv");
234 return { ssize_t(r) };
236 std::optional<size_t> recvmsg(msghdr* mh,
int flags) {
237 auto r = ::recvmsg(_fd, mh, flags);
238 if (r == -1 && errno == EAGAIN) {
241 throw_system_error_on(r == -1,
"recvmsg");
242 return { size_t(r) };
244 std::optional<size_t> send(
const void* buffer,
size_t len,
int flags) {
245 auto r = ::send(_fd, buffer, len, flags);
246 if (r == -1 && errno == EAGAIN) {
249 throw_system_error_on(r == -1,
"send");
250 return { size_t(r) };
252 std::optional<size_t> sendto(
socket_address& addr,
const void* buf,
size_t len,
int flags) {
253 auto r = ::sendto(_fd, buf, len, flags, &addr.
u.sa, addr.length());
254 if (r == -1 && errno == EAGAIN) {
257 throw_system_error_on(r == -1,
"sendto");
258 return { size_t(r) };
260 std::optional<size_t> sendmsg(
const msghdr* msg,
int flags) {
261 auto r = ::sendmsg(_fd, msg, flags);
262 if (r == -1 && errno == EAGAIN) {
265 throw_system_error_on(r == -1,
"sendmsg");
266 return { size_t(r) };
268 void bind(sockaddr& sa, socklen_t sl) {
269 auto r = ::bind(_fd, &sa, sl);
270 throw_system_error_on(r == -1,
"bind");
272 void connect(sockaddr& sa, socklen_t sl) {
274 if (r == -1 && errno == EINPROGRESS) {
277 throw_system_error_on(r == -1,
"connect");
281 auto r = ::getsockname(_fd, &addr.
u.sa, &addr.addr_length);
282 throw_system_error_on(r == -1,
"getsockname");
285 void listen(
int backlog) {
287 throw_system_error_on(fd == -1,
"listen");
289 std::optional<size_t> write(
const void* buf,
size_t len) {
290 auto r = ::write(_fd, buf, len);
291 if (r == -1 && errno == EAGAIN) {
294 throw_system_error_on(r == -1,
"write");
295 return { size_t(r) };
297 std::optional<size_t> writev(
const iovec *iov,
int iovcnt) {
298 auto r = ::writev(_fd, iov, iovcnt);
299 if (r == -1 && errno == EAGAIN) {
302 throw_system_error_on(r == -1,
"writev");
303 return { size_t(r) };
305 size_t pread(
void* buf,
size_t len, off_t off) {
306 auto r = ::pread(_fd, buf, len, off);
307 throw_system_error_on(r == -1,
"pread");
310 void timerfd_settime(
int flags,
const itimerspec& its) {
311 auto r = ::timerfd_settime(_fd, flags, &its, NULL);
312 throw_system_error_on(r == -1,
"timerfd_settime");
315 mmap_area map(
size_t size,
unsigned prot,
unsigned flags,
size_t offset,
316 void* addr =
nullptr) {
317 void *x = mmap(addr, size, prot, flags, _fd, offset);
318 throw_system_error_on(x == MAP_FAILED,
"mmap");
319 return mmap_area(
static_cast<char*
>(x),
mmap_deleter{size});
322 mmap_area map_shared_rw(
size_t size,
size_t offset) {
323 return map(size, PROT_READ | PROT_WRITE, MAP_SHARED, offset);
326 mmap_area map_shared_ro(
size_t size,
size_t offset) {
327 return map(size, PROT_READ, MAP_SHARED, offset);
330 mmap_area map_private_rw(
size_t size,
size_t offset) {
331 return map(size, PROT_READ | PROT_WRITE, MAP_PRIVATE, offset);
334 mmap_area map_private_ro(
size_t size,
size_t offset) {
335 return map(size, PROT_READ, MAP_PRIVATE, offset);
349 template <
typename Rep,
typename Period>
351 to_timespec(std::chrono::duration<Rep, Period> d) {
352 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count();
353 struct timespec ts {};
354 ts.tv_sec = ns / 1000000000;
355 ts.tv_nsec = ns % 1000000000;
364 template <
typename Rep1,
typename Period1,
typename Rep2,
typename Period2>
366 to_relative_itimerspec(std::chrono::duration<Rep1, Period1> base, std::chrono::duration<Rep2, Period2> interval) {
367 struct itimerspec its {};
379 template <
typename Clock,
class Duration,
class Rep,
class Period>
381 to_absolute_itimerspec(std::chrono::time_point<Clock, Duration> base, std::chrono::duration<Rep, Period> interval) {
392 std::unique_ptr<std::function<void ()>> _func;
397 static void* start_routine(
void* arg) noexcept;
409 template <
typename... A>
411 set(std::forward<A>(a)...);
414 template <
typename A,
typename... Rest>
415 void set(A a, Rest... rest) {
416 set(std::forward<A>(a));
417 set(std::forward<Rest>(rest)...);
419 void set(stack_size ss) { _stack_size = ss; }
421 stack_size _stack_size;
422 friend class posix_thread;
428 void throw_system_error_on(
bool condition,
const char* what_arg) {
433 throw std::system_error(errno, std::system_category(), what_arg);
437 template <
typename T>
439 void throw_kernel_error(T r) {
440 static_assert(std::is_signed<T>::value,
"kernel error variables must be signed");
446 throw std::system_error(-r, std::system_category());
450 template <
typename T>
452 void throw_pthread_error(T r) {
454 throw std::system_error(r, std::system_category());
459 sigset_t make_sigset_mask(
int signo) {
462 sigaddset(&set, signo);
467 sigset_t make_full_sigset_mask() {
474 sigset_t make_empty_sigset_mask() {
481 void pin_this_thread(
unsigned cpu_id) {
484 CPU_SET(cpu_id, &cs);
485 auto r = pthread_setaffinity_np(pthread_self(),
sizeof(cs), &cs);