LinuxTV Patchwork qv4l2: Prevent high CPU usage on device disconnect

login
register
mail settings
Submitter Tasos Sahanidis
Date May 9, 2019, 1:32 p.m.
Message ID <19b10673-7c90-5bb7-c596-94f73414d65e@tasossah.com>
Download mbox | patch
Permalink /patch/56081/
State New
Delegated to: Hans Verkuil
Headers show

Comments

Tasos Sahanidis - May 9, 2019, 1:32 p.m.
On device disconnect, ApplicationWindow::ctrlEvent() gets called
continuously, causing high CPU usage.
Closing the device handles once ENODEV is returned fixes this.
---
 utils/qv4l2/alsa_stream.c |  2 +-
 utils/qv4l2/qv4l2.cpp     | 24 +++++++++++++++++++-----
 2 files changed, 20 insertions(+), 6 deletions(-)

Patch

diff --git a/utils/qv4l2/alsa_stream.c b/utils/qv4l2/alsa_stream.c
index 05944822..2dca283b 100644
--- a/utils/qv4l2/alsa_stream.c
+++ b/utils/qv4l2/alsa_stream.c
@@ -433,7 +433,7 @@  static snd_pcm_sframes_t readbuf(snd_pcm_t *handle, char *buf, long len)
     snd_pcm_uframes_t frames;
     snd_pcm_htimestamp(handle, &frames, &timestamp);
     r = snd_pcm_readi(handle, buf, len);
-    if (r < 0 && r != -EAGAIN) {
+    if (r < 0 && !(r == -EAGAIN || r == -ENODEV)) {
 	r = snd_pcm_recover(handle, r, 0);
 	if (r < 0)
 	    fprintf(error_fp, "alsa: overrun recover error: %s\n", snd_strerror(r));
diff --git a/utils/qv4l2/qv4l2.cpp b/utils/qv4l2/qv4l2.cpp
index b52a3b60..9ac2c332 100644
--- a/utils/qv4l2/qv4l2.cpp
+++ b/utils/qv4l2/qv4l2.cpp
@@ -495,8 +495,9 @@  void ApplicationWindow::setAudioBufferSize()
 void ApplicationWindow::ctrlEvent()
 {
 	v4l2_event ev;
+	int event_ret = 0;
 
-	while (dqevent(ev) == 0) {
+	while ((event_ret = dqevent(ev)) == 0) {
 		if (ev.type == V4L2_EVENT_SOURCE_CHANGE) {
 			m_genTab->sourceChange(ev);
 			continue;
@@ -551,6 +552,15 @@  void ApplicationWindow::ctrlEvent()
 			setString(ev.id, c.string);
 		free(c.string);
 	}
+
+	if (event_ret && errno == ENODEV) {
+		closeDevice();
+		if (m_capture != NULL) {
+			m_capture->stop();
+			delete m_capture;
+			m_capture = NULL;
+		}
+	}
 }
 
 void ApplicationWindow::newCaptureWin()
@@ -558,6 +568,7 @@  void ApplicationWindow::newCaptureWin()
 	if (m_capture != NULL) {
 		m_capture->stop();
 		delete m_capture;
+		m_capture = NULL;
 	}
 
 	switch (m_renderMethod) {
@@ -1135,7 +1146,7 @@  void ApplicationWindow::stopStreaming()
 	if (!m_genTab->isSDR() && m_genTab->isRadio())
 		return;
 
-	if (v4l_type_is_capture(g_type()))
+	if (v4l_type_is_capture(g_type()) && m_capture != NULL)
 		m_capture->stop();
 
 	m_snapshotAct->setDisabled(true);
@@ -1561,8 +1572,10 @@  void ApplicationWindow::makeFullScreen(bool checked)
 void ApplicationWindow::closeDevice()
 {
 	stopAudio();
-	delete m_sigMapper;
-	m_sigMapper = NULL;
+	if(m_sigMapper != NULL) {
+		m_sigMapper->deleteLater();
+		m_sigMapper = NULL;
+	}
 	m_capStartAct->setEnabled(false);
 	m_capStartAct->setChecked(false);
 	m_capStepAct->setEnabled(false);
@@ -1579,7 +1592,7 @@  void ApplicationWindow::closeDevice()
 			m_outNotifier = NULL;
 		}
 		if (m_ctrlNotifier) {
-			delete m_ctrlNotifier;
+			m_ctrlNotifier->deleteLater();
 			m_ctrlNotifier = NULL;
 		}
 		delete [] m_frameData;
@@ -1740,6 +1753,7 @@  void ApplicationWindow::closeEvent(QCloseEvent *event)
 {
 	closeDevice();
 	delete m_capture;
+	m_capture = NULL;
 	event->accept();
 }
 

Privacy Policy