From 79a3607d0c220797ebf9449dd2d49221e2761fda Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 12 Dec 2020 22:01:01 +0100 Subject: [PATCH] Avoiding a lengthy lock on the Channels list when starting a recording --- CONTRIBUTORS | 1 + HISTORY | 2 ++ menu.c | 16 ++++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index c6efd469..1c1602f8 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3639,6 +3639,7 @@ Helmut Binder for fixing a bug in handling shared PMTs, where after the first pass not all SIDs of a PMT pid were checked any more for reporting a problem with PMT handling in case locking the Channels list times out + for avoiding a lengthy lock on the Channels list when starting a recording Ulrich Eckhardt for reporting a problem with shutdown after user inactivity in case a plugin is diff --git a/HISTORY b/HISTORY index b1167360..b0467e9e 100644 --- a/HISTORY +++ b/HISTORY @@ -9553,3 +9553,5 @@ Video Disk Recorder Revision History PMT pid were checked any more (thanks to Helmut Binder). - Fixed PMT handling in case locking the Channels list times out (reported by Helmut Binder). +- Avoiding a lengthy lock on the Channels list when starting a recording (thanks to + Helmut Binder). diff --git a/menu.c b/menu.c index 1a295dc7..724c0a22 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 4.87 2020/11/06 13:13:05 kls Exp $ + * $Id: menu.c 4.88 2020/12/12 22:01:01 kls Exp $ */ #include "menu.h" @@ -5229,6 +5229,11 @@ cRecordControl::cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer, const char *LastReplayed = cReplayControl::LastReplayed(); // must do this before locking schedules! // Whatever happens here, the timers will be modified in some way... Timers->SetModified(); + cStateKey ChannelsStateKey; + // To create a new timer, we need to make shure there is + // a lock on Channels prior to the Schedules locking below + if (!Timer) + cChannels::GetChannelsRead(ChannelsStateKey); // We're going to work with an event here, so we need to prevent // others from modifying any EPG data: cStateKey SchedulesStateKey; @@ -5244,6 +5249,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer, timer = new cTimer(true, Pause); Timers->Add(timer); instantId = cString::sprintf(cDevice::NumDevices() > 1 ? "%s - %d" : "%s", timer->Channel()->Name(), device->DeviceNumber() + 1); + ChannelsStateKey.Remove(); } timer->SetPending(true); timer->SetRecording(true); @@ -5380,7 +5386,8 @@ bool cRecordControls::Start(cTimers *Timers, cTimer *Timer, bool Pause) LastNoDiskSpaceMessage = 0; ChangeState(); - LOCK_CHANNELS_READ; + cStateKey StateKey; + const cChannels *Channels = cChannels::GetChannelsRead(StateKey); int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannel(); if (const cChannel *Channel = Channels->GetByNumber(ch)) { int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority; @@ -5388,9 +5395,12 @@ bool cRecordControls::Start(cTimers *Timers, cTimer *Timer, bool Pause) if (device) { dsyslog("switching device %d to channel %d %s (%s)", device->DeviceNumber() + 1, Channel->Number(), *Channel->GetChannelID().ToString(), Channel->Name()); if (!device->SwitchChannel(Channel, false)) { + StateKey.Remove(); ShutdownHandler.RequestEmergencyExit(); return false; } + StateKey.Remove(); + Channels = NULL; if (!Timer || Timer->Matches()) { for (int i = 0; i < MAXRECORDCONTROLS; i++) { if (!RecordControls[i]) { @@ -5407,6 +5417,8 @@ bool cRecordControls::Start(cTimers *Timers, cTimer *Timer, bool Pause) } else esyslog("ERROR: channel %d not defined!", ch); + if (Channels) + StateKey.Remove(); return false; }