diff options
| author | Klaus Schmidinger <vdr@tvdr.de> | 2013-12-24 14:41:09 +0100 | 
|---|---|---|
| committer | Klaus Schmidinger <vdr@tvdr.de> | 2013-12-24 14:41:09 +0100 | 
| commit | 7a2d3d993c932a12d17236f34a03f542c8943221 (patch) | |
| tree | df7233b94b8502a5fa16cd163d46c954855a6c15 | |
| parent | a9acab6b7ef720a6b5f4a9059f3d7843fb83777b (diff) | |
| download | vdr-7a2d3d993c932a12d17236f34a03f542c8943221.tar.gz vdr-7a2d3d993c932a12d17236f34a03f542c8943221.tar.bz2 | |
Fixed a possible crash if the recordings list is updated externally while the Recordings menu is open
| -rw-r--r-- | CONTRIBUTORS | 2 | ||||
| -rw-r--r-- | HISTORY | 4 | ||||
| -rw-r--r-- | recording.c | 69 | ||||
| -rw-r--r-- | recording.h | 8 | ||||
| -rw-r--r-- | vdr.c | 3 | 
5 files changed, 63 insertions, 23 deletions
| diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 712cc136..2c37d415 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2864,6 +2864,8 @@ Lars Hanisch <dvb@flensrocker.de>   used   for making the LIRC remote control connect to the socket even if it doesn't yet exist   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>   for adding tuning support for ATSC devices @@ -8032,7 +8032,7 @@ Video Disk Recorder Revision History    the last replayed recording (if any) by pressing Ok repeatedly in the Recordings    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    latitude of the antenna location is beyond +/-81 degrees. @@ -8065,3 +8065,5 @@ Video Disk Recorder Revision History    by Marko Mäkelä).  - Fixed uninitialized item area coordinates in cSkinLCARSDisplayMenu (reported by    Marko Mäkelä). +- Fixed a possible crash if the recordings list is updated externally while the +  Recordings menu is open (reported by Lars Hanisch). diff --git a/recording.c b/recording.c index d6ffb41e..f2577ab9 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * 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" @@ -76,6 +76,7 @@ bool DirectoryEncoding = false;  int InstanceId = 0;  cRecordings DeletedRecordings(true); +static cRecordings VanishedRecordings;  // --- 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(const char *FileName, bool IsPesRecording) @@ -1346,6 +1355,7 @@ cRecordings::cRecordings(bool Deleted)  :cThread("video directory scanner")  {    deleted = Deleted; +  initial = true;    lastUpdate = 0;    state = 0;  } @@ -1370,15 +1380,19 @@ const char *cRecordings::UpdateFileName(void)  void cRecordings::Refresh(bool Foreground)  {    lastUpdate = time(NULL); // doing this first to make sure we don't miss anything -  Lock(); -  Clear(); -  ChangeState(); -  Unlock(); +  initial = Count() == 0; // no name checking if the list is initially empty +  if (deleted) { +     Lock(); +     Clear(); +     ChangeState(); +     Unlock(); +     }    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);    struct dirent *e;    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 (endswith(buffer, deleted ? DELEXT : RECEXT)) { -                 cRecording *r = new cRecording(buffer); -                 if (r->Name()) { -                    r->NumFrames(); // initializes the numFrames member -                    r->FileSizeMB(); // initializes the fileSizeMB member -                    if (deleted) -                       r->deleted = time(NULL); -                    Lock(); -                    Add(r); -                    ChangeState(); -                    Unlock(); +                 if (deleted || initial || !GetByName(buffer)) { +                    cRecording *r = new cRecording(buffer); +                    if (r->Name()) { +                       r->NumFrames(); // initializes the numFrames member +                       r->FileSizeMB(); // initializes the fileSizeMB member +                       if (deleted) +                          r->deleted = time(NULL); +                       Lock(); +                       Add(r); +                       ChangeState(); +                       Unlock(); +                       } +                    else +                       delete r;                      } -                 else -                    delete r;                   }                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) @@ -1456,6 +1486,7 @@ bool cRecordings::Update(bool Wait)  cRecording *cRecordings::GetByName(const char *FileName)  {    if (FileName) { +     LOCK_THREAD;       for (cRecording *recording = First(); recording; recording = Next(recording)) {           if (strcmp(recording->FileName(), FileName) == 0)              return recording; diff --git a/recording.h b/recording.h index 3b00c71b..9baed31d 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * 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 @@ -41,6 +41,7 @@ enum eRecordingUsage {    };  void RemoveDeletedRecordings(void); +void ClearVanishedRecordings(void);  void AssertFreeDiskSpace(int Priority = 0, bool Force = false);       ///< The special Priority value -1 means that we shall get rid of any       ///< deleted recordings faster than normal (because we're cutting). @@ -217,11 +218,12 @@ class cRecordings : public cList<cRecording>, public cThread {  private:    static char *updateFileName;    bool deleted; +  bool initial;    time_t lastUpdate;    int state;    const char *UpdateFileName(void);    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:    void Action(void);  public: @@ -277,6 +279,8 @@ public:         ///< 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 DeletedRecordings; @@ -22,7 +22,7 @@   *   * 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> @@ -1369,6 +1369,7 @@ int main(int argc, char *argv[])             // Disk housekeeping:             RemoveDeletedRecordings(); +           ClearVanishedRecordings();             cSchedules::Cleanup();             // Plugins housekeeping:             PluginManager.Housekeeping(); | 
