From patchwork Fri Jul 12 11:04:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 1672 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 114D36156F for ; Fri, 12 Jul 2019 13:05:02 +0200 (CEST) Received: from pendragon.ideasonboard.com (softbank126209254147.bbtec.net [126.209.254.147]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 91E962B2 for ; Fri, 12 Jul 2019 13:04:59 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1562929500; bh=AxhS7VupOpgofRHankf2MzouTNyXI8dMf4Eu6a50f2s=; h=From:To:Subject:Date:From; b=AC59DIyRuJNFQ4ngK2NS5EL38H11ABSLm/eHjdO8+1sz4XY+yaEbnxjfUPqo5S2Vb UI25WAqIBhgvPun4GQAFQW/NBbBtSYbjXTl2Se+LefUDNtJoc4AkM8pccilKxom6mH a7ZVUD6LMAjuFd9zOMQ10/emFQAHoTBQ/aP2lJrc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 12 Jul 2019 14:04:28 +0300 Message-Id: <20190712110428.20433-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH] libcamera: event_notifier_poll: Fix notifier unregistration during event processing X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jul 2019 11:05:02 -0000 An event notifier may be unregistered from its activated signal. This can cause the notifiers set entry in notifiers_ to be deleted while processNotifiers() is looping over the notifiers_ map, leading to problems. To fix this, add a flag to the EventNotifierPoll class to indicate that event processing is in progress. If the flag is set, the notifiers_ entry is not deleted during notifier unregistration, but will be deleted by the event processing loop. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Niklas Söderlund --- src/libcamera/event_dispatcher_poll.cpp | 18 ++++++++++++++++++ src/libcamera/include/event_dispatcher_poll.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/libcamera/event_dispatcher_poll.cpp b/src/libcamera/event_dispatcher_poll.cpp index df9dffb2326c..4f15f3e3269b 100644 --- a/src/libcamera/event_dispatcher_poll.cpp +++ b/src/libcamera/event_dispatcher_poll.cpp @@ -46,6 +46,7 @@ static const char *notifierType(EventNotifier::Type type) */ EventDispatcherPoll::EventDispatcherPoll() + : processingEvents_(false) { /* * Create the event fd. Failures are fatal as we can't implement an @@ -96,6 +97,15 @@ void EventDispatcherPoll::unregisterEventNotifier(EventNotifier *notifier) } set.notifiers[type] = nullptr; + + /* + * Don't race with event processing if this method is called from an + * event notifier. The notifiers_ entry will be erased by + * processEvents(). + */ + if (processingEvents_) + return; + if (!set.notifiers[0] && !set.notifiers[1] && !set.notifiers[2]) notifiers_.erase(iter); } @@ -241,6 +251,8 @@ void EventDispatcherPoll::processNotifiers(const std::vector &pol { EventNotifier::Exception, POLLPRI }, }; + processingEvents_ = true; + for (const pollfd &pfd : pollfds) { auto iter = notifiers_.find(pfd.fd); ASSERT(iter != notifiers_.end()); @@ -269,7 +281,13 @@ void EventDispatcherPoll::processNotifiers(const std::vector &pol if (pfd.revents & event.events) notifier->activated.emit(notifier); } + + /* Erase the notifiers_ entry if it is now empty. */ + if (!set.notifiers[0] && !set.notifiers[1] && !set.notifiers[2]) + notifiers_.erase(iter); } + + processingEvents_ = false; } void EventDispatcherPoll::processTimers() diff --git a/src/libcamera/include/event_dispatcher_poll.h b/src/libcamera/include/event_dispatcher_poll.h index 14c3eea13b5e..d82b302c4aea 100644 --- a/src/libcamera/include/event_dispatcher_poll.h +++ b/src/libcamera/include/event_dispatcher_poll.h @@ -45,6 +45,8 @@ private: std::list timers_; int eventfd_; + bool processingEvents_; + int poll(std::vector *pollfds); void processInterrupt(const struct pollfd &pfd); void processNotifiers(const std::vector &pollfds);