From d370c1b46e1733905fd76eec004be26475afae9d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 23 Jan 2019 10:00:35 +0200 Subject: [PATCH] libcamera: event_dispatcher_poll: Handle interrupted ppoll() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ppoll() call can be interrupted if a signal is delivered. Handle the EINTR error code gracefully by restarting the call. This fixes the event-dispatcher test failure. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Niklas Söderlund --- src/libcamera/event_dispatcher_poll.cpp | 58 +++++++++++-------- src/libcamera/include/event_dispatcher_poll.h | 1 + 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/libcamera/event_dispatcher_poll.cpp b/src/libcamera/event_dispatcher_poll.cpp index eefac54ca..6e0609c34 100644 --- a/src/libcamera/event_dispatcher_poll.cpp +++ b/src/libcamera/event_dispatcher_poll.cpp @@ -128,6 +128,37 @@ void EventDispatcherPoll::processEvents() for (auto notifier : notifiers_) pollfds.push_back({ notifier.first, notifier.second.events(), 0 }); + /* Wait for events and process notifiers and timers. */ + do { + ret = poll(&pollfds); + } while (ret == -1 && errno == EINTR); + + if (ret < 0) { + ret = -errno; + LOG(Event, Warning) << "poll() failed with " << strerror(-ret); + } else if (ret > 0) { + processNotifiers(pollfds); + } + + processTimers(); +} + +short EventDispatcherPoll::EventNotifierSetPoll::events() const +{ + short events = 0; + + if (notifiers[EventNotifier::Read]) + events |= POLLIN; + if (notifiers[EventNotifier::Write]) + events |= POLLOUT; + if (notifiers[EventNotifier::Exception]) + events |= POLLPRI; + + return events; +} + +int EventDispatcherPoll::poll(std::vector *pollfds) +{ /* Compute the timeout. */ Timer *nextTimer = !timers_.empty() ? timers_.front() : nullptr; struct timespec timeout; @@ -151,31 +182,8 @@ void EventDispatcherPoll::processEvents() << timeout.tv_nsec; } - /* Wait for events and process notifiers and timers. */ - ret = ppoll(pollfds.data(), pollfds.size(), - nextTimer ? &timeout : nullptr, nullptr); - if (ret < 0) { - ret = -errno; - LOG(Event, Warning) << "poll() failed with " << strerror(-ret); - } else if (ret > 0) { - processNotifiers(pollfds); - } - - processTimers(); -} - -short EventDispatcherPoll::EventNotifierSetPoll::events() const -{ - short events = 0; - - if (notifiers[EventNotifier::Read]) - events |= POLLIN; - if (notifiers[EventNotifier::Write]) - events |= POLLOUT; - if (notifiers[EventNotifier::Exception]) - events |= POLLPRI; - - return events; + return ppoll(pollfds->data(), pollfds->size(), + nextTimer ? &timeout : nullptr, nullptr); } void EventDispatcherPoll::processNotifiers(const std::vector &pollfds) diff --git a/src/libcamera/include/event_dispatcher_poll.h b/src/libcamera/include/event_dispatcher_poll.h index a41926e11..ac3efde08 100644 --- a/src/libcamera/include/event_dispatcher_poll.h +++ b/src/libcamera/include/event_dispatcher_poll.h @@ -41,6 +41,7 @@ private: std::map notifiers_; std::list timers_; + int poll(std::vector *pollfds); void processNotifiers(const std::vector &pollfds); void processTimers(); };