Fixed a possible crash if the recordings list is updated externally while the Recordings menu is open

This commit is contained in:
Klaus Schmidinger 2013-12-24 14:41:09 +01:00
parent a9acab6b7e
commit 7a2d3d993c
5 changed files with 63 additions and 23 deletions

View File

@ -2864,6 +2864,8 @@ Lars Hanisch <dvb@flensrocker.de>
used used
for making the LIRC remote control connect to the socket even if it doesn't yet exist for making the LIRC remote control connect to the socket even if it doesn't yet exist
when VDR is started when VDR is started
for reporting a possible crash if the recordings list is updated externally while the
Recordings menu is open
Alex Lasnier <alex@fepg.org> Alex Lasnier <alex@fepg.org>
for adding tuning support for ATSC devices for adding tuning support for ATSC devices

View File

@ -8032,7 +8032,7 @@ Video Disk Recorder Revision History
the last replayed recording (if any) by pressing Ok repeatedly in the Recordings the last replayed recording (if any) by pressing Ok repeatedly in the Recordings
menu. menu.
2013-11-15: Version 2.1.3 2013-12-24: Version 2.1.3
- Changed the return value of cPositioner::HorizonLongitude() to 0 in case the - Changed the return value of cPositioner::HorizonLongitude() to 0 in case the
latitude of the antenna location is beyond +/-81 degrees. latitude of the antenna location is beyond +/-81 degrees.
@ -8065,3 +8065,5 @@ Video Disk Recorder Revision History
by Marko Mäkelä). by Marko Mäkelä).
- Fixed uninitialized item area coordinates in cSkinLCARSDisplayMenu (reported by - Fixed uninitialized item area coordinates in cSkinLCARSDisplayMenu (reported by
Marko Mäkelä). Marko Mäkelä).
- Fixed a possible crash if the recordings list is updated externally while the
Recordings menu is open (reported by Lars Hanisch).

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.c 3.8 2013/10/20 09:51:23 kls Exp $ * $Id: recording.c 3.9 2013/12/24 14:32:29 kls Exp $
*/ */
#include "recording.h" #include "recording.h"
@ -76,6 +76,7 @@ bool DirectoryEncoding = false;
int InstanceId = 0; int InstanceId = 0;
cRecordings DeletedRecordings(true); cRecordings DeletedRecordings(true);
static cRecordings VanishedRecordings;
// --- cRemoveDeletedRecordingsThread ---------------------------------------- // --- cRemoveDeletedRecordingsThread ----------------------------------------
@ -220,6 +221,14 @@ void AssertFreeDiskSpace(int Priority, bool Force)
} }
} }
// --- Clear vanished recordings ---------------------------------------------
void ClearVanishedRecordings(void)
{
cThreadLock RecordingsLock(&Recordings); // yes, it *is* Recordings!
VanishedRecordings.Clear();
}
// --- cResumeFile ----------------------------------------------------------- // --- cResumeFile -----------------------------------------------------------
cResumeFile::cResumeFile(const char *FileName, bool IsPesRecording) cResumeFile::cResumeFile(const char *FileName, bool IsPesRecording)
@ -1346,6 +1355,7 @@ cRecordings::cRecordings(bool Deleted)
:cThread("video directory scanner") :cThread("video directory scanner")
{ {
deleted = Deleted; deleted = Deleted;
initial = true;
lastUpdate = 0; lastUpdate = 0;
state = 0; state = 0;
} }
@ -1370,15 +1380,19 @@ const char *cRecordings::UpdateFileName(void)
void cRecordings::Refresh(bool Foreground) void cRecordings::Refresh(bool Foreground)
{ {
lastUpdate = time(NULL); // doing this first to make sure we don't miss anything lastUpdate = time(NULL); // doing this first to make sure we don't miss anything
Lock(); initial = Count() == 0; // no name checking if the list is initially empty
Clear(); if (deleted) {
ChangeState(); Lock();
Unlock(); Clear();
ChangeState();
Unlock();
}
ScanVideoDir(cVideoDirectory::Name(), Foreground); ScanVideoDir(cVideoDirectory::Name(), Foreground);
} }
void cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel) void cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel, int DirLevel)
{ {
// Find any new recordings:
cReadDir d(DirName); cReadDir d(DirName);
struct dirent *e; struct dirent *e;
while ((Foreground || Running()) && (e = d.Next()) != NULL) { while ((Foreground || Running()) && (e = d.Next()) != NULL) {
@ -1397,25 +1411,41 @@ void cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLev
} }
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
if (endswith(buffer, deleted ? DELEXT : RECEXT)) { if (endswith(buffer, deleted ? DELEXT : RECEXT)) {
cRecording *r = new cRecording(buffer); if (deleted || initial || !GetByName(buffer)) {
if (r->Name()) { cRecording *r = new cRecording(buffer);
r->NumFrames(); // initializes the numFrames member if (r->Name()) {
r->FileSizeMB(); // initializes the fileSizeMB member r->NumFrames(); // initializes the numFrames member
if (deleted) r->FileSizeMB(); // initializes the fileSizeMB member
r->deleted = time(NULL); if (deleted)
Lock(); r->deleted = time(NULL);
Add(r); Lock();
ChangeState(); Add(r);
Unlock(); ChangeState();
Unlock();
}
else
delete r;
} }
else
delete r;
} }
else else
ScanVideoDir(buffer, Foreground, LinkLevel + Link); ScanVideoDir(buffer, Foreground, LinkLevel + Link, DirLevel + 1);
} }
} }
} }
// Handle any vanished recordings:
if (!deleted && !initial && DirLevel == 0) {
for (cRecording *recording = First(); recording; ) {
cRecording *r = recording;
recording = Next(recording);
if (access(r->FileName(), F_OK) != 0) {
Lock();
Del(r, false);
VanishedRecordings.Add(r);
ChangeState();
Unlock();
}
}
}
} }
bool cRecordings::StateChanged(int &State) bool cRecordings::StateChanged(int &State)
@ -1456,6 +1486,7 @@ bool cRecordings::Update(bool Wait)
cRecording *cRecordings::GetByName(const char *FileName) cRecording *cRecordings::GetByName(const char *FileName)
{ {
if (FileName) { if (FileName) {
LOCK_THREAD;
for (cRecording *recording = First(); recording; recording = Next(recording)) { for (cRecording *recording = First(); recording; recording = Next(recording)) {
if (strcmp(recording->FileName(), FileName) == 0) if (strcmp(recording->FileName(), FileName) == 0)
return recording; return recording;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.h 3.1 2013/10/10 12:08:15 kls Exp $ * $Id: recording.h 3.2 2013/12/24 13:32:18 kls Exp $
*/ */
#ifndef __RECORDING_H #ifndef __RECORDING_H
@ -41,6 +41,7 @@ enum eRecordingUsage {
}; };
void RemoveDeletedRecordings(void); void RemoveDeletedRecordings(void);
void ClearVanishedRecordings(void);
void AssertFreeDiskSpace(int Priority = 0, bool Force = false); void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
///< The special Priority value -1 means that we shall get rid of any ///< The special Priority value -1 means that we shall get rid of any
///< deleted recordings faster than normal (because we're cutting). ///< deleted recordings faster than normal (because we're cutting).
@ -217,11 +218,12 @@ class cRecordings : public cList<cRecording>, public cThread {
private: private:
static char *updateFileName; static char *updateFileName;
bool deleted; bool deleted;
bool initial;
time_t lastUpdate; time_t lastUpdate;
int state; int state;
const char *UpdateFileName(void); const char *UpdateFileName(void);
void Refresh(bool Foreground = false); void Refresh(bool Foreground = false);
void ScanVideoDir(const char *DirName, bool Foreground = false, int LinkLevel = 0); void ScanVideoDir(const char *DirName, bool Foreground = false, int LinkLevel = 0, int DirLevel = 0);
protected: protected:
void Action(void); void Action(void);
public: public:
@ -277,6 +279,8 @@ public:
///< if all recordings have been successfully added to the RecordingsHandler. ///< if all recordings have been successfully added to the RecordingsHandler.
}; };
/// Any access to Recordings that loops through the list of recordings
/// needs to hold a thread lock on this object!
extern cRecordings Recordings; extern cRecordings Recordings;
extern cRecordings DeletedRecordings; extern cRecordings DeletedRecordings;

3
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.tvdr.de * The project's page is at http://www.tvdr.de
* *
* $Id: vdr.c 3.4 2013/10/16 09:33:58 kls Exp $ * $Id: vdr.c 3.5 2013/12/24 13:19:55 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -1369,6 +1369,7 @@ int main(int argc, char *argv[])
// Disk housekeeping: // Disk housekeeping:
RemoveDeletedRecordings(); RemoveDeletedRecordings();
ClearVanishedRecordings();
cSchedules::Cleanup(); cSchedules::Cleanup();
// Plugins housekeeping: // Plugins housekeeping:
PluginManager.Housekeeping(); PluginManager.Housekeeping();