1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Fixed a crash when moving a recording to a folder on a different volume

This commit is contained in:
Klaus Schmidinger 2016-12-13 13:54:00 +01:00
parent a9bd3ca0dc
commit 08066065e3
6 changed files with 46 additions and 44 deletions

View File

@ -8828,7 +8828,7 @@ Video Disk Recorder Revision History
- Empty adaptation field TS packets are now skipped when recording (thanks to
Christopher Reimer, based on the "AFFcleaner" by Stefan Pöschel).
2016-12-11: Version 2.3.2
2016-12-13: Version 2.3.2
- Fixed a crash when deleting a recording (reported by Oliver Endriss).
- Fixed an overflow of PIDs in a receiver (thanks to Robert Hannebauer).
@ -8847,3 +8847,7 @@ Video Disk Recorder Revision History
- Fixed setting the current item and counter values in the Recordings menu after
deleting the last recording in a subfolder.
- Fixed a crash when deleting a recording that is currently being replayed.
- Fixed a crash when moving a recording to a folder on a different volume.
The cRecordingsHandler now performs its actual operations in a separate thread,
thus avoiding locking problems and reducing the time between subsequent
operations.

12
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 4.17 2016/12/11 12:43:55 kls Exp $
* $Id: menu.c 4.18 2016/12/13 12:49:10 kls Exp $
*/
#include "menu.h"
@ -2687,14 +2687,15 @@ eOSState cMenuRecordingEdit::ApplyChanges(void)
cRecordings *Recordings = cRecordings::GetRecordingsWrite(StateKey);
cRecording *Recording = Recordings->GetByName(recording->FileName());
if (!Recording) {
StateKey.Remove(false);
Skins.Message(mtWarning, tr("Recording vanished!"));
return osBack;
}
bool Modified = false;
if (priority != recording->Priority() || lifetime != recording->Lifetime()) {
if (!Recording->ChangePriorityLifetime(priority, lifetime)) {
Skins.Message(mtError, tr("Error while changing priority/lifetime!"));
StateKey.Remove(Modified);
Skins.Message(mtError, tr("Error while changing priority/lifetime!"));
return osContinue;
}
Modified = true;
@ -2707,8 +2708,8 @@ eOSState cMenuRecordingEdit::ApplyChanges(void)
NewName.CompactChars(FOLDERDELIMCHAR);
if (strcmp(NewName, Recording->Name())) {
if (!Recording->ChangeName(NewName)) {
Skins.Message(mtError, tr("Error while changing folder/name!"));
StateKey.Remove(Modified);
Skins.Message(mtError, tr("Error while changing folder/name!"));
return osContinue;
}
Modified = true;
@ -3095,13 +3096,12 @@ eOSState cMenuRecordings::Delete(void)
if (const cRecording *Recording = Recordings->GetByName(ri->Recording()->FileName())) {
FileName = Recording->FileName();
if (RecordingsHandler.GetUsage(FileName)) {
if (Interface->Confirm(tr("Recording is being edited - really delete?")))
RecordingsHandler.Del(FileName);
else
if (!Interface->Confirm(tr("Recording is being edited - really delete?")))
return osContinue;
}
}
}
RecordingsHandler.Del(FileName); // must do this w/o holding a lock, because the cleanup section in cDirCopier::Action() might request one!
if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName) == 0)
cControl::Shutdown();
cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 4.4 2015/09/09 10:21:58 kls Exp $
* $Id: recording.c 4.5 2016/12/13 13:39:09 kls Exp $
*/
#include "recording.h"
@ -1701,7 +1701,7 @@ void cDirCopier::Action(void)
int To = -1;
size_t BufferSize = BUFSIZ;
while (Running()) {
// Suspend cutting if we have severe throughput problems:
// Suspend copying if we have severe throughput problems:
if (Throttled()) {
cCondWait::SleepMs(100);
continue;
@ -1900,6 +1900,7 @@ bool cRecordingsHandlerEntry::Active(bool &Error)
cRecordingsHandler RecordingsHandler;
cRecordingsHandler::cRecordingsHandler(void)
:cThread("recordings handler")
{
finished = true;
error = false;
@ -1907,6 +1908,23 @@ cRecordingsHandler::cRecordingsHandler(void)
cRecordingsHandler::~cRecordingsHandler()
{
Cancel(3);
}
void cRecordingsHandler::Action(void)
{
while (Running()) {
{
cMutexLock MutexLock(&mutex);
while (cRecordingsHandlerEntry *r = operations.First()) {
if (!r->Active(error))
operations.Del(r);
}
if (!operations.Count())
break;
}
cCondWait::SleepMs(100);
}
}
cRecordingsHandlerEntry *cRecordingsHandler::Get(const char *FileName)
@ -1934,8 +1952,7 @@ bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *Fil
Usage |= ruPending;
operations.Add(new cRecordingsHandlerEntry(Usage, FileNameSrc, FileNameDst));
finished = false;
Active(); // start it right away if possible
LOCK_RECORDINGS_WRITE; // to trigger a state change
Start();
return true;
}
else
@ -1955,17 +1972,17 @@ bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *Fil
void cRecordingsHandler::Del(const char *FileName)
{
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = Get(FileName)) {
if (cRecordingsHandlerEntry *r = Get(FileName))
operations.Del(r);
LOCK_RECORDINGS_WRITE; // to trigger a state change
}
}
void cRecordingsHandler::DelAll(void)
{
{
cMutexLock MutexLock(&mutex);
operations.Clear();
LOCK_RECORDINGS_WRITE; // to trigger a state change
}
Cancel(3);
}
int cRecordingsHandler::GetUsage(const char *FileName)
@ -1976,18 +1993,6 @@ int cRecordingsHandler::GetUsage(const char *FileName)
return ruNone;
}
bool cRecordingsHandler::Active(void)
{
cMutexLock MutexLock(&mutex);
while (cRecordingsHandlerEntry *r = operations.First()) {
if (r->Active(error))
return true;
else
operations.Del(r);
}
return false;
}
bool cRecordingsHandler::Finished(bool &Error)
{
cMutexLock MutexLock(&mutex);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.h 4.3 2015/08/29 14:12:14 kls Exp $
* $Id: recording.h 4.4 2016/12/13 13:12:12 kls Exp $
*/
#ifndef __RECORDING_H
@ -302,16 +302,18 @@ DEF_LIST_LOCK2(Recordings, DeletedRecordings);
class cRecordingsHandlerEntry;
class cRecordingsHandler {
class cRecordingsHandler : public cThread {
private:
cMutex mutex;
cList<cRecordingsHandlerEntry> operations;
bool finished;
bool error;
cRecordingsHandlerEntry *Get(const char *FileName);
protected:
virtual void Action(void);
public:
cRecordingsHandler(void);
~cRecordingsHandler();
virtual ~cRecordingsHandler();
bool Add(int Usage, const char *FileNameSrc, const char *FileNameDst = NULL);
///< Adds the given FileNameSrc to the recordings handler for (later)
///< processing. Usage can be either ruCut, ruMove or ruCopy. FileNameDst
@ -329,12 +331,6 @@ public:
///< Deletes/terminates all operations.
int GetUsage(const char *FileName);
///< Returns the usage type for the given FileName.
bool Active(void);
///< Checks whether there is currently any operation running and starts
///> the next one form the list if the previous one has finished.
///< This function must be called regularly to trigger switching to the
///< next operation in the list.
///< Returns true if there are any operations in the list.
bool Finished(bool &Error);
///< Returns true if all operations in the list have been finished.
///< If there have been any errors, Errors will be set to true.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 4.3 2015/09/06 10:45:54 kls Exp $
* $Id: tools.h 4.4 2016/12/13 12:13:46 kls Exp $
*/
#ifndef __TOOLS_H
@ -609,7 +609,7 @@ public: \
else \
list = c##Class::Get##Name##Read(stateKey); \
} \
~c##Name##Lock() { stateKey.Remove(); } \
~c##Name##Lock() { if (list) stateKey.Remove(); } \
const c##Class *Name(void) const { return list; } \
c##Class *Name(void) { return const_cast<c##Class *>(list); } \
}

5
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.tvdr.de
*
* $Id: vdr.c 4.7 2015/09/11 08:02:50 kls Exp $
* $Id: vdr.c 4.8 2016/12/13 13:13:10 kls Exp $
*/
#include <getopt.h>
@ -1480,9 +1480,6 @@ int main(int argc, char *argv[])
ShutdownHandler.countdown.Cancel();
}
// Keep the recordings handler alive:
RecordingsHandler.Active();
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
// Handle housekeeping tasks