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:
parent
83c73c39c5
commit
d370c1b46e
2 changed files with 34 additions and 25 deletions
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue