Fix: common: poll: compat_poll_wait never finishes
[lttng-tools.git] / src / common / compat / compat-poll.c
index 79756f5731fa48dd41ac2c646333c4f1080278b3..01de4f5489c578ebfcdd9caf50ca95920f8b1163 100644 (file)
@@ -1,19 +1,9 @@
 /*
- * Copyright (C)  2011 - David Goulet <david.goulet@polymtl.ca>
- * Copyright (C)  2019 - Yannick Lamarre <ylamarre@efficios.com>
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2019 Yannick Lamarre <ylamarre@efficios.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _LGPL_SOURCE
@@ -307,14 +297,12 @@ int compat_poll_wait(struct lttng_poll_event *events, int timeout,
                bool interruptible)
 {
        int ret, active_fd_count;
-       int idle_pfd_index = 0;
-       size_t i;
+       size_t pos = 0, consecutive_entries = 0, non_idle_pos;
 
        if (events == NULL || events->current.events == NULL) {
                ERR("poll wait arguments error");
                goto error;
        }
-       assert(events->current.nb_fd >= 0);
 
        if (events->current.nb_fd == 0) {
                /* Return an invalid error to be consistent with epoll. */
@@ -344,34 +332,36 @@ int compat_poll_wait(struct lttng_poll_event *events, int timeout,
        active_fd_count = ret;
 
        /*
-        * Swap all active pollfd structs to the beginning of the
-        * array to emulate compat-epoll behaviour. This algorithm takes
-        * advantage of poll's returned value and the burst nature of active
-        * events on the file descriptors. The while loop guarantees that
-        * idle_pfd will always point to an idle fd.
+        * Move all active pollfd structs to the beginning of the
+        * array to emulate compat-epoll behaviour.
         */
        if (active_fd_count == events->wait.nb_fd) {
                goto end;
        }
-       while (idle_pfd_index < active_fd_count &&
-                       events->wait.events[idle_pfd_index].revents != 0) {
-               idle_pfd_index++;
-       }
 
-       for (i = idle_pfd_index + 1; idle_pfd_index < active_fd_count;
-                       i++) {
-               struct pollfd swap_pfd;
-               struct pollfd *idle_pfd = &events->wait.events[idle_pfd_index];
-               struct pollfd *current_pfd = &events->wait.events[i];
-
-               if (idle_pfd->revents != 0) {
-                       swap_pfd = *current_pfd;
-                       *current_pfd = *idle_pfd;
-                       *idle_pfd = swap_pfd;
-                       idle_pfd_index++;
+       while (consecutive_entries != active_fd_count) {
+               struct pollfd *current = &events->wait.events[pos];
+               struct pollfd idle_entry;
+
+               if (current->revents != 0) {
+                       consecutive_entries++;
+                       pos++;
+                       continue;
                }
-       }
 
+               non_idle_pos = pos;
+
+               /* Look for next non-idle entry. */
+               while (events->wait.events[++non_idle_pos].revents == 0);
+
+               /* Swap idle and non-idle entries. */
+               idle_entry = *current;
+               *current = events->wait.events[non_idle_pos];
+               events->wait.events[non_idle_pos] = idle_entry;
+
+               consecutive_entries++;
+               pos++;
+       }
 end:
        return ret;
 
This page took 0.032921 seconds and 4 git commands to generate.