Ticket #12046: 0001-Fix-random-SBE-PlaybackSock-timeout-in-MBE.patch

File 0001-Fix-random-SBE-PlaybackSock-timeout-in-MBE.patch, 4.4 KB (added by Cédric Schieli <cschieli@…>, 7 years ago)

Fix random SBE PlaybackSock? timeout in MBE

  • mythtv/programs/mythbackend/mainserver.cpp

    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) 
    443443
    444444void MainServer::ProcessRequestWork(MythSocket *sock)
    445445{
     446    sockListLock.lockForRead();
     447    PlaybackSock *pbs = GetPlaybackBySock(sock);
     448    if (pbs)
     449        pbs->IncrRef();
     450    sockListLock.unlock();
     451
    446452    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())
    448464    {
    449465        LOG(VB_GENERAL, LOG_INFO, "No data in ProcessRequestWork()");
    450466        return;
    void MainServer::ProcessRequestWork(MythSocket *sock) 
    475491    }
    476492
    477493    sockListLock.lockForRead();
    478     PlaybackSock *pbs = GetPlaybackBySock(sock);
     494    pbs = GetPlaybackBySock(sock);
    479495    if (!pbs)
    480496    {
    481497        sockListLock.unlock();
  • mythtv/programs/mythbackend/playbacksock.cpp

    diff --git a/mythtv/programs/mythbackend/playbacksock.cpp b/mythtv/programs/mythbackend/playbacksock.cpp
    index d482fda..957dc19 100644
    a b using namespace std; 
    1010#include "mythcorecontext.h"
    1111#include "mythdate.h"
    1212#include "inputinfo.h"
     13#include "referencecounter.h"
    1314
    1415#define LOC QString("PlaybackSock: ")
    1516#define LOC_ERR QString("PlaybackSock, Error: ")
    PlaybackSockEventsMode PlaybackSock::eventsMode(void) const 
    7172    return m_eventsMode;
    7273}
    7374
     75bool 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
    7489bool PlaybackSock::SendReceiveStringList(
    7590    QStringList &strlist, uint min_reply_length)
    7691{
  • mythtv/programs/mythbackend/playbacksock.h

    diff --git a/mythtv/programs/mythbackend/playbacksock.h b/mythtv/programs/mythbackend/playbacksock.h
    index 4452222..ea2d125 100644
    a b class PlaybackSock : public ReferenceCounter 
    101101
    102102    QStringList ForwardRequest(const QStringList&);
    103103
     104    bool ReadStringList(QStringList &list);
     105
    104106  private:
    105107    bool SendReceiveStringList(QStringList &strlist, uint min_reply_length = 0);
    106108