Tests: Fix: Use '.logfile' instead of '.log' for test app output
[lttng-tools.git] / src / common / compat / poll.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-only
6 *
7 */
8
9 #define _LGPL_SOURCE
10 #include "poll.hpp"
11
12 #include <common/defaults.hpp>
13 #include <common/error.hpp>
14 #include <common/macros.hpp>
15 #include <common/utils.hpp>
16
17 #include <stdbool.h>
18 #include <stdlib.h>
19
20 #ifdef HAVE_EPOLL
21
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 /*
29 * Maximum number of fd we can monitor.
30 *
31 * For epoll(7), /proc/sys/fs/epoll/max_user_watches (since Linux 2.6.28) will
32 * be used for the maximum size of the poll set. If this interface is not
33 * available, according to the manpage, the max_user_watches value is 1/25 (4%)
34 * of the available low memory divided by the registration cost in bytes which
35 * is 90 bytes on a 32-bit kernel and 160 bytes on a 64-bit kernel.
36 *
37 */
38 static unsigned int poll_max_size;
39
40 /*
41 * Resize the epoll events structure of the new size.
42 *
43 * Return 0 on success or else -1 with the current events pointer untouched.
44 */
45 static int resize_poll_event(struct lttng_poll_event *events, uint32_t new_size)
46 {
47 struct epoll_event *ptr;
48
49 LTTNG_ASSERT(events);
50
51 ptr = (epoll_event *) realloc(events->events, new_size * sizeof(*ptr));
52 if (ptr == nullptr) {
53 PERROR("realloc epoll add");
54 goto error;
55 }
56 if (new_size > events->alloc_size) {
57 /* Zero newly allocated memory */
58 memset(ptr + events->alloc_size, 0, (new_size - events->alloc_size) * sizeof(*ptr));
59 }
60 events->events = ptr;
61 events->alloc_size = new_size;
62
63 return 0;
64
65 error:
66 return -1;
67 }
68
69 /*
70 * Create epoll set and allocate returned events structure.
71 */
72 int compat_epoll_create(struct lttng_poll_event *events, int count, int flags)
73 {
74 int ret;
75
76 if (events == nullptr || count <= 0) {
77 goto error;
78 }
79
80 if (!poll_max_size) {
81 if (lttng_poll_set_max_size()) {
82 goto error;
83 }
84 }
85
86 /* Don't bust the limit here */
87 if (count > poll_max_size) {
88 count = poll_max_size;
89 }
90
91 ret = compat_glibc_epoll_create(count, flags);
92 if (ret < 0) {
93 /* At this point, every error is fatal */
94 PERROR("epoll_create1");
95 goto error;
96 }
97
98 events->epfd = ret;
99
100 /* This *must* be freed by using lttng_poll_free() */
101 events->events = calloc<epoll_event>(count);
102 if (events->events == nullptr) {
103 PERROR("zmalloc epoll set");
104 goto error_close;
105 }
106
107 events->alloc_size = events->init_size = count;
108 events->nb_fd = 0;
109
110 return 0;
111
112 error_close:
113 ret = close(events->epfd);
114 if (ret) {
115 PERROR("close");
116 }
117 error:
118 return -1;
119 }
120
121 /*
122 * Add a fd to the epoll set with requesting events.
123 */
124 int compat_epoll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
125 {
126 int ret;
127 struct epoll_event ev;
128
129 if (events == nullptr || events->events == nullptr || fd < 0) {
130 ERR("Bad compat epoll add arguments");
131 goto error;
132 }
133
134 /*
135 * Zero struct epoll_event to ensure all representations of its
136 * union are zeroed.
137 */
138 memset(&ev, 0, sizeof(ev));
139 ev.events = req_events;
140 ev.data.fd = fd;
141
142 ret = epoll_ctl(events->epfd, EPOLL_CTL_ADD, fd, &ev);
143 if (ret < 0) {
144 switch (errno) {
145 case EEXIST:
146 /* If exist, it's OK. */
147 goto end;
148 case ENOSPC:
149 case EPERM:
150 /* Print PERROR and goto end not failing. Show must go on. */
151 PERROR("epoll_ctl ADD");
152 goto end;
153 default:
154 PERROR("epoll_ctl ADD fatal");
155 goto error;
156 }
157 }
158
159 events->nb_fd++;
160
161 end:
162 return 0;
163
164 error:
165 return -1;
166 }
167
168 /*
169 * Remove a fd from the epoll set.
170 */
171 int compat_epoll_del(struct lttng_poll_event *events, int fd)
172 {
173 int ret;
174
175 if (events == nullptr || fd < 0 || events->nb_fd == 0) {
176 goto error;
177 }
178
179 ret = epoll_ctl(events->epfd, EPOLL_CTL_DEL, fd, nullptr);
180 if (ret < 0) {
181 switch (errno) {
182 case ENOENT:
183 case EPERM:
184 /* Print PERROR and goto end not failing. Show must go on. */
185 PERROR("epoll_ctl DEL");
186 goto end;
187 default:
188 PERROR("epoll_ctl DEL fatal");
189 goto error;
190 }
191 }
192
193 events->nb_fd--;
194
195 end:
196 return 0;
197
198 error:
199 return -1;
200 }
201
202 /*
203 * Set an fd's events.
204 */
205 int compat_epoll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events)
206 {
207 int ret;
208 struct epoll_event ev;
209
210 if (events == nullptr || fd < 0 || events->nb_fd == 0) {
211 goto error;
212 }
213
214 /*
215 * Zero struct epoll_event to ensure all representations of its
216 * union are zeroed.
217 */
218 memset(&ev, 0, sizeof(ev));
219 ev.events = req_events;
220 ev.data.fd = fd;
221
222 ret = epoll_ctl(events->epfd, EPOLL_CTL_MOD, fd, &ev);
223 if (ret < 0) {
224 switch (errno) {
225 case ENOENT:
226 case EPERM:
227 /* Print PERROR and goto end not failing. Show must go on. */
228 PERROR("epoll_ctl MOD");
229 goto end;
230 default:
231 PERROR("epoll_ctl MOD fatal");
232 goto error;
233 }
234 }
235
236 end:
237 return 0;
238
239 error:
240 return -1;
241 }
242
243 /*
244 * Wait on epoll set. This is a blocking call of timeout value.
245 */
246 int compat_epoll_wait(struct lttng_poll_event *events, int timeout, bool interruptible)
247 {
248 int ret;
249 uint32_t new_size;
250
251 if (events == nullptr || events->events == nullptr) {
252 ERR("Wrong arguments in compat_epoll_wait");
253 goto error;
254 }
255
256 if (events->nb_fd == 0) {
257 errno = EINVAL;
258 return -1;
259 }
260
261 /*
262 * Resize if needed before waiting. We could either expand the array or
263 * shrink it down. It's important to note that after this step, we are
264 * ensured that the events argument of the epoll_wait call will be large
265 * enough to hold every possible returned events.
266 */
267 new_size = 1U << utils_get_count_order_u32(events->nb_fd);
268 if (new_size != events->alloc_size && new_size >= events->init_size) {
269 ret = resize_poll_event(events, new_size);
270 if (ret < 0) {
271 /* ENOMEM problem at this point. */
272 goto error;
273 }
274 }
275
276 do {
277 ret = epoll_wait(events->epfd, events->events, events->nb_fd, timeout);
278 } while (!interruptible && ret == -1 && errno == EINTR);
279 if (ret < 0) {
280 if (errno != EINTR) {
281 PERROR("epoll_wait");
282 }
283 goto error;
284 }
285
286 /*
287 * Since the returned events are set sequentially in the "events" structure
288 * we only need to return the epoll_wait value and iterate over it.
289 */
290 return ret;
291
292 error:
293 return -1;
294 }
295
296 /*
297 * Setup poll set maximum size.
298 */
299 int compat_epoll_set_max_size()
300 {
301 int ret, fd, retval = 0;
302 ssize_t size_ret;
303 char buf[64];
304
305 fd = open(COMPAT_EPOLL_PROC_PATH, O_RDONLY);
306 if (fd < 0) {
307 /*
308 * Failing on opening [1] is not an error per see. [1] was
309 * introduced in Linux 2.6.28 but epoll is available since
310 * 2.5.44. Hence, goto end and set a default value without
311 * setting an error return value.
312 *
313 * [1] /proc/sys/fs/epoll/max_user_watches
314 */
315 retval = 0;
316 goto end;
317 }
318
319 size_ret = lttng_read(fd, buf, sizeof(buf));
320 /*
321 * Allow reading a file smaller than buf, but keep space for
322 * final \0.
323 */
324 if (size_ret < 0 || size_ret >= sizeof(buf)) {
325 PERROR("read set max size");
326 retval = -1;
327 goto end_read;
328 }
329 buf[size_ret] = '\0';
330 poll_max_size = atoi(buf);
331 end_read:
332 ret = close(fd);
333 if (ret) {
334 PERROR("close");
335 }
336 end:
337 if (!poll_max_size) {
338 poll_max_size = DEFAULT_POLL_SIZE;
339 }
340 DBG("epoll set max size is %d", poll_max_size);
341 return retval;
342 }
343
344 #else /* HAVE_EPOLL */
345
346 #include <sys/resource.h>
347 #include <sys/time.h>
348
349 /*
350 * Maximum number of fd we can monitor.
351 *
352 * For poll(2), the max fds must not exceed RLIMIT_NOFILE given by
353 * getrlimit(2).
354 */
355 static unsigned int poll_max_size;
356
357 /*
358 * Resize the epoll events structure of the new size.
359 *
360 * Return 0 on success or else -1 with the current events pointer untouched.
361 */
362 static int resize_poll_event(struct compat_poll_event_array *array, uint32_t new_size)
363 {
364 struct pollfd *ptr;
365
366 LTTNG_ASSERT(array);
367
368 /* Refuse to resize the array more than the max size. */
369 if (new_size > poll_max_size) {
370 goto error;
371 }
372
373 ptr = (struct pollfd *) realloc(array->events, new_size * sizeof(*ptr));
374 if (ptr == NULL) {
375 PERROR("realloc epoll add");
376 goto error;
377 }
378 if (new_size > array->alloc_size) {
379 /* Zero newly allocated memory */
380 memset(ptr + array->alloc_size, 0, (new_size - array->alloc_size) * sizeof(*ptr));
381 }
382 array->events = ptr;
383 array->alloc_size = new_size;
384
385 return 0;
386
387 error:
388 return -1;
389 }
390
391 /*
392 * Update events with the current events object.
393 */
394 static int update_current_events(struct lttng_poll_event *events)
395 {
396 int ret;
397 struct compat_poll_event_array *current, *wait;
398
399 LTTNG_ASSERT(events);
400
401 current = &events->current;
402 wait = &events->wait;
403
404 wait->nb_fd = current->nb_fd;
405 if (current->alloc_size != wait->alloc_size) {
406 ret = resize_poll_event(wait, current->alloc_size);
407 if (ret < 0) {
408 goto error;
409 }
410 }
411 memcpy(wait->events, current->events, current->nb_fd * sizeof(*current->events));
412
413 /* Update is done. */
414 events->need_update = 0;
415
416 return 0;
417
418 error:
419 return -1;
420 }
421
422 /*
423 * Create pollfd data structure.
424 */
425 int compat_poll_create(struct lttng_poll_event *events, int size)
426 {
427 struct compat_poll_event_array *current, *wait;
428
429 if (events == NULL || size <= 0) {
430 ERR("Wrong arguments for poll create");
431 goto error;
432 }
433
434 if (!poll_max_size) {
435 if (lttng_poll_set_max_size()) {
436 goto error;
437 }
438 }
439
440 /* Don't bust the limit here */
441 if (size > poll_max_size) {
442 size = poll_max_size;
443 }
444
445 /* Reset everything before begining the allocation. */
446 memset(events, 0, sizeof(struct lttng_poll_event));
447
448 current = &events->current;
449 wait = &events->wait;
450
451 /* This *must* be freed by using lttng_poll_free() */
452 wait->events = calloc<struct pollfd>(size);
453 if (wait->events == NULL) {
454 PERROR("Failed to allocate wait events array during poll initialization");
455 goto error;
456 }
457
458 wait->alloc_size = wait->init_size = size;
459
460 current->events = calloc<struct pollfd>(size);
461 if (current->events == NULL) {
462 PERROR("Failed to allocate current events array during poll initialization");
463 goto error;
464 }
465
466 current->alloc_size = current->init_size = size;
467
468 return 0;
469
470 error:
471 return -1;
472 }
473
474 /*
475 * Add fd to pollfd data structure with requested events.
476 */
477 int compat_poll_add(struct lttng_poll_event *events, int fd, uint32_t req_events)
478 {
479 int new_size, ret, i;
480 struct compat_poll_event_array *current;
481
482 if (events == NULL || events->current.events == NULL || fd < 0) {
483 ERR("Bad compat poll add arguments");
484 goto error;
485 }
486
487 current = &events->current;
488
489 /* Check if fd we are trying to add is already there. */
490 for (i = 0; i < current->nb_fd; i++) {
491 if (current->events[i].fd == fd) {
492 errno = EEXIST;
493 goto error;
494 }
495 }
496
497 /* Resize array if needed. */
498 new_size = 1U << utils_get_count_order_u32(current->nb_fd + 1);
499 if (new_size != current->alloc_size && new_size >= current->init_size) {
500 ret = resize_poll_event(current, new_size);
501 if (ret < 0) {
502 goto error;
503 }
504 }
505
506 current->events[current->nb_fd].fd = fd;
507 current->events[current->nb_fd].events = req_events;
508 current->nb_fd++;
509 events->need_update = 1;
510
511 DBG("fd %d of %d added to pollfd", fd, current->nb_fd);
512
513 return 0;
514
515 error:
516 return -1;
517 }
518
519 /*
520 * Modify an fd's events..
521 */
522 int compat_poll_mod(struct lttng_poll_event *events, int fd, uint32_t req_events)
523 {
524 int i;
525 struct compat_poll_event_array *current;
526
527 if (events == NULL || events->current.nb_fd == 0 || events->current.events == NULL ||
528 fd < 0) {
529 ERR("Bad compat poll mod arguments");
530 goto error;
531 }
532
533 current = &events->current;
534
535 for (i = 0; i < current->nb_fd; i++) {
536 if (current->events[i].fd == fd) {
537 current->events[i].events = req_events;
538 events->need_update = 1;
539 break;
540 }
541 }
542
543 /*
544 * The epoll flavor doesn't flag modifying a non-included FD as an
545 * error.
546 */
547
548 return 0;
549
550 error:
551 return -1;
552 }
553
554 /*
555 * Remove a fd from the pollfd structure.
556 */
557 int compat_poll_del(struct lttng_poll_event *events, int fd)
558 {
559 int i, count = 0, ret;
560 uint32_t new_size;
561 struct compat_poll_event_array *current;
562
563 if (events == NULL || events->current.nb_fd == 0 || events->current.events == NULL ||
564 fd < 0) {
565 goto error;
566 }
567
568 /* Ease our life a bit. */
569 current = &events->current;
570
571 for (i = 0; i < current->nb_fd; i++) {
572 /* Don't put back the fd we want to delete */
573 if (current->events[i].fd != fd) {
574 current->events[count].fd = current->events[i].fd;
575 current->events[count].events = current->events[i].events;
576 count++;
577 }
578 }
579
580 /* The fd was not in our set, return no error as with epoll. */
581 if (current->nb_fd == count) {
582 goto end;
583 }
584
585 /* No fd duplicate should be ever added into array. */
586 LTTNG_ASSERT(current->nb_fd - 1 == count);
587 current->nb_fd = count;
588
589 /* Resize array if needed. */
590 new_size = 1U << utils_get_count_order_u32(current->nb_fd);
591 if (new_size != current->alloc_size && new_size >= current->init_size &&
592 current->nb_fd != 0) {
593 ret = resize_poll_event(current, new_size);
594 if (ret < 0) {
595 goto error;
596 }
597 }
598
599 events->need_update = 1;
600
601 end:
602 return 0;
603
604 error:
605 return -1;
606 }
607
608 /*
609 * Wait on poll() with timeout. Blocking call.
610 */
611 int compat_poll_wait(struct lttng_poll_event *events, int timeout, bool interruptible)
612 {
613 int ret, active_fd_count;
614 size_t pos = 0, consecutive_entries = 0, non_idle_pos;
615
616 if (events == NULL || events->current.events == NULL) {
617 ERR("poll wait arguments error");
618 goto error;
619 }
620
621 if (events->current.nb_fd == 0) {
622 /* Return an invalid error to be consistent with epoll. */
623 errno = EINVAL;
624 events->wait.nb_fd = 0;
625 goto error;
626 }
627
628 if (events->need_update) {
629 ret = update_current_events(events);
630 if (ret < 0) {
631 errno = ENOMEM;
632 goto error;
633 }
634 }
635
636 do {
637 ret = poll(events->wait.events, events->wait.nb_fd, timeout);
638 } while (!interruptible && ret == -1 && errno == EINTR);
639 if (ret < 0) {
640 if (errno != EINTR) {
641 PERROR("poll wait");
642 }
643 goto error;
644 }
645
646 active_fd_count = ret;
647
648 /*
649 * Move all active pollfd structs to the beginning of the
650 * array to emulate compat-epoll behaviour.
651 */
652 if (active_fd_count == events->wait.nb_fd) {
653 goto end;
654 }
655
656 while (consecutive_entries != active_fd_count) {
657 struct pollfd *current = &events->wait.events[pos];
658 struct pollfd idle_entry;
659
660 if (current->revents != 0) {
661 consecutive_entries++;
662 pos++;
663 continue;
664 }
665
666 non_idle_pos = pos;
667
668 /* Look for next non-idle entry. */
669 while (events->wait.events[++non_idle_pos].revents == 0)
670 ;
671
672 /* Swap idle and non-idle entries. */
673 idle_entry = *current;
674 *current = events->wait.events[non_idle_pos];
675 events->wait.events[non_idle_pos] = idle_entry;
676
677 consecutive_entries++;
678 pos++;
679 }
680 end:
681 return ret;
682
683 error:
684 return -1;
685 }
686
687 /*
688 * Setup poll set maximum size.
689 */
690 int compat_poll_set_max_size(void)
691 {
692 int ret, retval = 0;
693 struct rlimit lim;
694
695 ret = getrlimit(RLIMIT_NOFILE, &lim);
696 if (ret < 0) {
697 PERROR("getrlimit poll RLIMIT_NOFILE");
698 retval = -1;
699 goto end;
700 }
701
702 poll_max_size = lim.rlim_cur;
703 end:
704 if (poll_max_size == 0) {
705 poll_max_size = DEFAULT_POLL_SIZE;
706 }
707 DBG("poll set max size set to %u", poll_max_size);
708 return retval;
709 }
710
711 #endif /* !HAVE_EPOLL */
This page took 0.043737 seconds and 5 git commands to generate.