26#include <sys/eventfd.h>
29#include <sys/socket.h>
31#include <sys/timerfd.h>
41#include <system_error>
49#include "abort_on_ebadf.hh"
50#include <seastar/core/sstring.hh>
51#include <seastar/net/socket_defs.hh>
52#include <seastar/util/std-compat.hh>
53#include <seastar/util/modules.hh>
57SEASTAR_MODULE_EXPORT_BEGIN
68inline void throw_system_error_on(
bool condition,
const char* what_arg =
"");
71inline void throw_kernel_error(T r);
74inline void throw_pthread_error(T r);
78 void operator()(
void* ptr)
const;
81using mmap_area = std::unique_ptr<char[], mmap_deleter>;
83mmap_area mmap_anonymous(
void* addr,
size_t length,
int prot,
int flags);
91 ~file_desc() {
if (_fd != -1) { ::close(_fd); } }
92 void operator=(
const file_desc&) =
delete;
95 std::swap(_fd, x._fd);
104 auto r = ::close(_fd);
105 throw_system_error_on(r == -1,
"close");
108 int get()
const {
return _fd; }
110 sstring fdinfo()
const noexcept;
116 static file_desc open(sstring name,
int flags, mode_t mode = 0) {
117 int fd = ::open(name.c_str(), flags, mode);
118 throw_system_error_on(fd == -1,
"open");
122 int fd = ::socket(family, type, protocol);
123 throw_system_error_on(fd == -1,
"socket");
126 static file_desc eventfd(
unsigned initval,
int flags) {
127 int fd = ::eventfd(initval, flags);
128 throw_system_error_on(fd == -1,
"eventfd");
131 static file_desc epoll_create(
int flags = 0) {
132 int fd = ::epoll_create1(flags);
133 throw_system_error_on(fd == -1,
"epoll_create1");
136 static file_desc timerfd_create(
int clockid,
int flags) {
137 int fd = ::timerfd_create(clockid, flags);
138 throw_system_error_on(fd == -1,
"timerfd_create");
141 static file_desc temporary(sstring directory);
143 int fd = ::dup(get());
144 throw_system_error_on(fd == -1,
"dup");
148 auto ret = ::accept4(_fd, &sa.as_posix_sockaddr(), &sa.addr_length, flags);
149 throw_system_error_on(ret == -1,
"accept4");
152 static file_desc inotify_init(
int flags);
154 std::optional<file_desc> try_accept(
socket_address& sa,
int flags = 0) {
155 auto ret = ::accept4(_fd, &sa.as_posix_sockaddr(), &sa.addr_length, flags);
156 if (ret == -1 && errno == EAGAIN) {
159 throw_system_error_on(ret == -1,
"accept4");
162 void shutdown(
int how) {
163 auto ret = ::shutdown(_fd, how);
164 if (ret == -1 && errno != ENOTCONN) {
165 throw_system_error_on(ret == -1,
"shutdown");
168 void truncate(
size_t size) {
169 auto ret = ::ftruncate(_fd, size);
170 throw_system_error_on(ret,
"ftruncate");
172 int ioctl(
int request) {
173 return ioctl(request, 0);
175 int ioctl(
int request,
int value) {
176 int r = ::ioctl(_fd, request, value);
177 throw_system_error_on(r == -1,
"ioctl");
180 int ioctl(
int request,
unsigned int value) {
181 int r = ::ioctl(_fd, request, value);
182 throw_system_error_on(r == -1,
"ioctl");
186 int ioctl(
int request, X& data) {
187 int r = ::ioctl(_fd, request, &data);
188 throw_system_error_on(r == -1,
"ioctl");
192 int ioctl(
int request, X&& data) {
193 int r = ::ioctl(_fd, request, &data);
194 throw_system_error_on(r == -1,
"ioctl");
198 int setsockopt(
int level,
int optname, X&& data) {
199 int r = ::setsockopt(_fd, level, optname, &data,
sizeof(data));
200 throw_system_error_on(r == -1,
"setsockopt");
203 int setsockopt(
int level,
int optname,
const char* data) {
204 int r = ::setsockopt(_fd, level, optname, data, strlen(data) + 1);
205 throw_system_error_on(r == -1,
"setsockopt");
208 int setsockopt(
int level,
int optname,
const void* data, socklen_t len) {
209 int r = ::setsockopt(_fd, level, optname, data, len);
210 throw_system_error_on(r == -1,
"setsockopt");
213 template <
typename Data>
214 Data getsockopt(
int level,
int optname) {
216 socklen_t len =
sizeof(data);
217 memset(&data, 0, len);
218 int r = ::getsockopt(_fd, level, optname, &data, &len);
219 throw_system_error_on(r == -1,
"getsockopt");
222 int getsockopt(
int level,
int optname,
char* data, socklen_t len) {
223 int r = ::getsockopt(_fd, level, optname, data, &len);
224 throw_system_error_on(r == -1,
"getsockopt");
229 auto r = ::fstat(_fd, &buf);
230 throw_system_error_on(r == -1,
"fstat");
233 std::optional<size_t> read(
void* buffer,
size_t len) {
234 auto r = ::read(_fd, buffer, len);
235 if (r == -1 && errno == EAGAIN) {
238 throw_system_error_on(r == -1,
"read");
239 return { size_t(r) };
241 std::optional<ssize_t> recv(
void* buffer,
size_t len,
int flags) {
242 auto r = ::recv(_fd, buffer, len, flags);
243 if (r == -1 && errno == EAGAIN) {
246 throw_system_error_on(r == -1,
"recv");
247 return { ssize_t(r) };
249 std::optional<size_t> recvmsg(msghdr* mh,
int flags) {
250 auto r = ::recvmsg(_fd, mh, flags);
251 if (r == -1 && errno == EAGAIN) {
254 throw_system_error_on(r == -1,
"recvmsg");
255 return { size_t(r) };
257 std::optional<size_t> send(
const void* buffer,
size_t len,
int flags) {
258 auto r = ::send(_fd, buffer, len, flags);
259 if (r == -1 && errno == EAGAIN) {
262 throw_system_error_on(r == -1,
"send");
263 return { size_t(r) };
265 std::optional<size_t> sendto(
socket_address& addr,
const void* buf,
size_t len,
int flags) {
266 auto r = ::sendto(_fd, buf, len, flags, &addr.
u.sa, addr.length());
267 if (r == -1 && errno == EAGAIN) {
270 throw_system_error_on(r == -1,
"sendto");
271 return { size_t(r) };
273 std::optional<size_t> sendmsg(
const msghdr* msg,
int flags) {
274 auto r = ::sendmsg(_fd, msg, flags);
275 if (r == -1 && errno == EAGAIN) {
278 throw_system_error_on(r == -1,
"sendmsg");
279 return { size_t(r) };
281 void bind(sockaddr& sa, socklen_t sl) {
282 auto r = ::bind(_fd, &sa, sl);
283 throw_system_error_on(r == -1,
"bind");
285 void connect(sockaddr& sa, socklen_t sl) {
287 if (r == -1 && errno == EINPROGRESS) {
290 throw_system_error_on(r == -1,
"connect");
294 auto r = ::getsockname(_fd, &addr.
u.sa, &addr.addr_length);
295 throw_system_error_on(r == -1,
"getsockname");
300 auto r = ::getpeername(_fd, &addr.
u.sa, &addr.addr_length);
301 throw_system_error_on(r == -1,
"getpeername");
304 void listen(
int backlog) {
306 throw_system_error_on(fd == -1,
"listen");
308 std::optional<size_t> write(
const void* buf,
size_t len) {
309 auto r = ::write(_fd, buf, len);
310 if (r == -1 && errno == EAGAIN) {
313 throw_system_error_on(r == -1,
"write");
314 return { size_t(r) };
316 std::optional<size_t> writev(
const iovec *iov,
int iovcnt) {
317 auto r = ::writev(_fd, iov, iovcnt);
318 if (r == -1 && errno == EAGAIN) {
321 throw_system_error_on(r == -1,
"writev");
322 return { size_t(r) };
324 size_t pread(
void* buf,
size_t len, off_t off) {
325 auto r = ::pread(_fd, buf, len, off);
326 throw_system_error_on(r == -1,
"pread");
329 void timerfd_settime(
int flags,
const itimerspec& its) {
330 auto r = ::timerfd_settime(_fd, flags, &its, NULL);
331 throw_system_error_on(r == -1,
"timerfd_settime");
334 mmap_area map(
size_t size,
unsigned prot,
unsigned flags,
size_t offset,
335 void* addr =
nullptr) {
336 void *x = mmap(addr, size, prot, flags, _fd, offset);
337 throw_system_error_on(x == MAP_FAILED,
"mmap");
338 return mmap_area(
static_cast<char*
>(x),
mmap_deleter{size});
341 mmap_area map_shared_rw(
size_t size,
size_t offset) {
342 return map(size, PROT_READ | PROT_WRITE, MAP_SHARED, offset);
345 mmap_area map_shared_ro(
size_t size,
size_t offset) {
346 return map(size, PROT_READ, MAP_SHARED, offset);
349 mmap_area map_private_rw(
size_t size,
size_t offset) {
350 return map(size, PROT_READ | PROT_WRITE, MAP_PRIVATE, offset);
353 mmap_area map_private_ro(
size_t size,
size_t offset) {
354 return map(size, PROT_READ, MAP_PRIVATE, offset);
357 void spawn_actions_add_close(posix_spawn_file_actions_t* actions) {
358 auto r = ::posix_spawn_file_actions_addclose(actions, _fd);
359 throw_pthread_error(r);
362 void spawn_actions_add_dup2(posix_spawn_file_actions_t* actions,
int newfd) {
363 auto r = ::posix_spawn_file_actions_adddup2(actions, _fd, newfd);
364 throw_pthread_error(r);
373constexpr unsigned rcv_shutdown = 0x1;
374constexpr unsigned snd_shutdown = 0x2;
375inline constexpr unsigned shutdown_mask(
int how) {
return how + 1; }
381template <
typename Rep,
typename Period>
384 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count();
385 struct timespec ts {};
386 ts.tv_sec = ns / 1000000000;
387 ts.tv_nsec = ns % 1000000000;
396template <
typename Rep1,
typename Period1,
typename Rep2,
typename Period2>
399 struct itimerspec its {};
411template <
typename Clock,
class Duration,
class Rep,
class Period>
424 std::unique_ptr<std::function<void ()>> _func;
429 static void* start_routine(
void* arg)
noexcept;
441 template <
typename... A>
443 set(std::forward<A>(a)...);
446 template <
typename A,
typename... Rest>
447 void set(A a, Rest... rest) {
448 set(std::forward<A>(a));
449 set(std::forward<Rest>(rest)...);
451 void set(stack_size ss) { _stack_size = ss; }
452 void set(cpu_set_t affinity) { _affinity = affinity; }
454 stack_size _stack_size;
455 std::optional<cpu_set_t> _affinity;
456 friend class posix_thread;
462void throw_system_error_on(
bool condition,
const char* what_arg) {
467 throw std::system_error(errno, std::system_category(), what_arg);
473void throw_kernel_error(T r) {
474 static_assert(std::is_signed_v<T>,
"kernel error variables must be signed");
480 throw std::system_error(-r, std::system_category());
486void throw_pthread_error(T r) {
488 throw std::system_error(r, std::system_category());
493sigset_t make_sigset_mask(
int signo) {
496 sigaddset(&set, signo);
501sigset_t make_full_sigset_mask() {
508sigset_t make_empty_sigset_mask() {
515void pin_this_thread(
unsigned cpu_id) {
518 CPU_SET(cpu_id, &cs);
519 auto r = pthread_setaffinity_np(pthread_self(),
sizeof(cs), &cs);
524std::set<unsigned> get_current_cpuset();
528SEASTAR_MODULE_EXPORT_END
Definition: socket_defs.hh:47
union seastar::socket_address::@14 u
!< actual size of the relevant 'u' member
server_socket listen(socket_address sa)
future< connected_socket > connect(socket_address sa)
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
bool is_abort_on_ebadf_enabled()
struct itimerspec to_relative_itimerspec(std::chrono::duration< Rep1, Period1 > base, std::chrono::duration< Rep2, Period2 > interval)
Definition: posix.hh:398
struct itimerspec to_absolute_itimerspec(std::chrono::time_point< Clock, Duration > base, std::chrono::duration< Rep, Period > interval)
Definition: posix.hh:413
struct timespec to_timespec(std::chrono::duration< Rep, Period > d)
Definition: posix.hh:383