libcamera: event_dispatcher_poll: Handle interrupted ppoll() calls

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 <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
Laurent Pinchart 2019-01-23 10:00:35 +02:00
parent 83c73c39c5
commit d370c1b46e
2 changed files with 34 additions and 25 deletions

View file

@ -128,6 +128,37 @@ void EventDispatcherPoll::processEvents()
for (auto notifier : notifiers_) for (auto notifier : notifiers_)
pollfds.push_back({ notifier.first, notifier.second.events(), 0 }); 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<struct pollfd> *pollfds)
{
/* Compute the timeout. */ /* Compute the timeout. */
Timer *nextTimer = !timers_.empty() ? timers_.front() : nullptr; Timer *nextTimer = !timers_.empty() ? timers_.front() : nullptr;
struct timespec timeout; struct timespec timeout;
@ -151,31 +182,8 @@ void EventDispatcherPoll::processEvents()
<< timeout.tv_nsec; << timeout.tv_nsec;
} }
/* Wait for events and process notifiers and timers. */ return ppoll(pollfds->data(), pollfds->size(),
ret = ppoll(pollfds.data(), pollfds.size(), nextTimer ? &timeout : nullptr, nullptr);
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;
} }
void EventDispatcherPoll::processNotifiers(const std::vector<struct pollfd> &pollfds) void EventDispatcherPoll::processNotifiers(const std::vector<struct pollfd> &pollfds)

View file

@ -41,6 +41,7 @@ private:
std::map<int, EventNotifierSetPoll> notifiers_; std::map<int, EventNotifierSetPoll> notifiers_;
std::list<Timer *> timers_; std::list<Timer *> timers_;
int poll(std::vector<struct pollfd> *pollfds);
void processNotifiers(const std::vector<struct pollfd> &pollfds); void processNotifiers(const std::vector<struct pollfd> &pollfds);
void processTimers(); void processTimers();
}; };