From 5a0e47676c9b85c5072ba54c1e1fc426736998f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Schieli?= <cschieli@gmail.com>
Date: Sat, 1 Feb 2014 10:35:28 +0100
Subject: Fix random SBE PlaybackSock timeout in MBE.
SBE PlaybackSocks in the master suffer from random disconnection, occuring
after a 7000 ms timeout. It often happens when a frontend ask for the
thumbnail of a program currently being recorded on a slave backend.
I could identify two problems causing this:
First, there is a race between MainServer::ProcessRequestWork and
PlaybackSock::SendReceiveStringList. Even if callbacks are disabled during
SendReceiveStringList execution, a ProcessRequestWork may already be running
and can swallow the reply, leading to the timeout in SendReceiveStringList.
The second problem is that an invocation of ProcessRequestWork is fired for
each block of data arriving in the socket (for example when a reply is long
enough to be fragmented, ie. GENERATED_PIXMAP) but this data is consumed all at
once by one worker, leaving the other workers without food. This also leads to
the timeout in ReadStringList.
This patch fixes the first problem by assuring that no worker reads from the
socket while a SendReceiveStringList is running and the second one by aborting
a worker if there is no more data to read, but only once the lock has been
acquired.
---
mythtv/programs/mythbackend/mainserver.cpp | 20 ++++++++++++++++++--
mythtv/programs/mythbackend/playbacksock.cpp | 15 +++++++++++++++
mythtv/programs/mythbackend/playbacksock.h | 2 ++
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/mythtv/programs/mythbackend/mainserver.cpp b/mythtv/programs/mythbackend/mainserver.cpp
index a717556..6b573d7 100644
a
|
b
|
void MainServer::ProcessRequest(MythSocket *sock) |
443 | 443 | |
444 | 444 | void MainServer::ProcessRequestWork(MythSocket *sock) |
445 | 445 | { |
| 446 | sockListLock.lockForRead(); |
| 447 | PlaybackSock *pbs = GetPlaybackBySock(sock); |
| 448 | if (pbs) |
| 449 | pbs->IncrRef(); |
| 450 | sockListLock.unlock(); |
| 451 | |
446 | 452 | QStringList listline; |
447 | | if (!sock->ReadStringList(listline) || listline.empty()) |
| 453 | if (pbs) |
| 454 | { |
| 455 | if (!pbs->ReadStringList(listline) || listline.empty()) |
| 456 | { |
| 457 | pbs->DecrRef(); |
| 458 | LOG(VB_GENERAL, LOG_INFO, "No data in ProcessRequestWork()"); |
| 459 | return; |
| 460 | } |
| 461 | pbs->DecrRef(); |
| 462 | } |
| 463 | else if (!sock->ReadStringList(listline) || listline.empty()) |
448 | 464 | { |
449 | 465 | LOG(VB_GENERAL, LOG_INFO, "No data in ProcessRequestWork()"); |
450 | 466 | return; |
… |
… |
void MainServer::ProcessRequestWork(MythSocket *sock) |
475 | 491 | } |
476 | 492 | |
477 | 493 | sockListLock.lockForRead(); |
478 | | PlaybackSock *pbs = GetPlaybackBySock(sock); |
| 494 | pbs = GetPlaybackBySock(sock); |
479 | 495 | if (!pbs) |
480 | 496 | { |
481 | 497 | sockListLock.unlock(); |
diff --git a/mythtv/programs/mythbackend/playbacksock.cpp b/mythtv/programs/mythbackend/playbacksock.cpp
index d482fda..957dc19 100644
a
|
b
|
using namespace std; |
10 | 10 | #include "mythcorecontext.h" |
11 | 11 | #include "mythdate.h" |
12 | 12 | #include "inputinfo.h" |
| 13 | #include "referencecounter.h" |
13 | 14 | |
14 | 15 | #define LOC QString("PlaybackSock: ") |
15 | 16 | #define LOC_ERR QString("PlaybackSock, Error: ") |
… |
… |
PlaybackSockEventsMode PlaybackSock::eventsMode(void) const |
71 | 72 | return m_eventsMode; |
72 | 73 | } |
73 | 74 | |
| 75 | bool PlaybackSock::ReadStringList(QStringList &list) |
| 76 | { |
| 77 | sock->IncrRef(); |
| 78 | ReferenceLocker rlocker(sock); |
| 79 | QMutexLocker locker(&sockLock); |
| 80 | if (!sock->IsDataAvailable()) |
| 81 | { |
| 82 | LOG(VB_GENERAL, LOG_DEBUG, |
| 83 | "PlaybackSock::ReadStringList(): Data vanished !!!"); |
| 84 | return false; |
| 85 | } |
| 86 | return sock->ReadStringList(list); |
| 87 | } |
| 88 | |
74 | 89 | bool PlaybackSock::SendReceiveStringList( |
75 | 90 | QStringList &strlist, uint min_reply_length) |
76 | 91 | { |
diff --git a/mythtv/programs/mythbackend/playbacksock.h b/mythtv/programs/mythbackend/playbacksock.h
index 4452222..ea2d125 100644
a
|
b
|
class PlaybackSock : public ReferenceCounter |
101 | 101 | |
102 | 102 | QStringList ForwardRequest(const QStringList&); |
103 | 103 | |
| 104 | bool ReadStringList(QStringList &list); |
| 105 | |
104 | 106 | private: |
105 | 107 | bool SendReceiveStringList(QStringList &strlist, uint min_reply_length = 0); |
106 | 108 | |