diff --git a/menu_commands.c b/menu_commands.c
index 99ca744..028bd99 100644
--- a/menu_commands.c
+++ b/menu_commands.c
@@ -182,7 +182,7 @@ eOSState cMenuSearchCommands::MarkAsRecorded(void)
         return osContinue;
     cTimer* dummyTimer = new cTimer(event);
     cMutexLock RecsDoneLock(&RecsDone);
-    RecsDone.Add(new cRecDone(dummyTimer, event, search));
+    RecsDone.Add(new cRecDone(dummyTimer, event, search, "Unused"));
     RecsDone.Save();
     delete dummyTimer;
     return osBack;
diff --git a/recdone.c b/recdone.c
index 53780cd..ce63ffe 100644
--- a/recdone.c
+++ b/recdone.c
@@ -48,15 +48,20 @@ cRecDone::cRecDone()
     buffer = NULL;
     searchID = -1;
     rawdescription = NULL;
+    fileName = NULL;
 }
 
-cRecDone::cRecDone(const cTimer* Timer, const cEvent* Event, cSearchExt* Search)
+cRecDone::cRecDone(const cTimer* Timer, const cEvent* Event, cSearchExt* Search, const char* Name)
 {
     title = shortText = description = aux = rawdescription = NULL;
     startTime = 0;
+    timerStart = 0;
+    timerStop = 0;
+    vpsused = false;
     duration = 0;
     searchID = Search ? Search->ID : -1;
     buffer = NULL;
+    fileName = strdup(Name);
 
     if (Event) {
         if (Event->Title())
@@ -71,6 +76,9 @@ cRecDone::cRecDone(const cTimer* Timer, const cEvent* Event, cSearchExt* Search)
             channelID = Timer->Channel()->GetChannelID();
             if (!isempty(Timer->Aux()))
                 aux = strdup(Timer->Aux());
+            timerStart = Timer->StartTime();
+            timerStop = Timer->StopTime();
+            vpsused = Timer->HasFlags(tfVps) && Event->Vps();
         } else {
             channelID = tChannelID::InvalidID;
             aux = NULL;
@@ -104,6 +112,10 @@ cRecDone::~cRecDone()
         free(aux);
         aux = NULL;
     }
+    if (fileName) {
+        free(fileName);
+        fileName = NULL;
+    }
 
 }
 
diff --git a/recdone.h b/recdone.h
index cfad67f..6cfa50b 100644
--- a/recdone.h
+++ b/recdone.h
@@ -38,17 +38,21 @@ public:
     char *title;             // Title of this event
     char *shortText;         // Short description of this event
     char *description;       // Description of this event
+    char *fileName;          // Name used in MsgRecording
     char *aux;               // Aux info
-    time_t startTime;        // Start time of the timer
-    int duration;
-    int searchID;          // ID of the search, that triggered this recording
+    time_t startTime;        // Start time of the event
+    time_t timerStart;       // Start time of the timer
+    time_t timerStop;        // Stop time of the timer
+    bool vpsused;
+    int duration;            // Duration of event
+    int searchID;            // ID of the search, that triggered this recording
     tChannelID channelID;
 
     char* rawdescription;
     static char *buffer;
 
     cRecDone();
-    cRecDone(const cTimer*, const cEvent* event, cSearchExt* search);
+    cRecDone(const cTimer*, const cEvent* event, cSearchExt* search, const char* name);
     ~cRecDone();
 
     static bool Read(FILE *f);
diff --git a/recdone_thread.c b/recdone_thread.c
index 6b0e02b..77d45b8 100644
--- a/recdone_thread.c
+++ b/recdone_thread.c
@@ -80,57 +80,82 @@ void cRecdoneThread::Action(void)
     time_t now = time(NULL);
     // remove timers that finished recording from TimersRecording
     // incomplete recordings are kept for a while, perhaps they will be resumed
-    LOCK_TIMERS_READ;
     while (m_fnames.size()) {
         vector<string>::iterator it = m_fnames.begin();
         const char *m_filename = (*it).c_str();
         LogFile.Log(1, "recdone_thread processing %s", m_filename);
+        dsyslog("epgsearch: recdone_thread processing %s", m_filename);
+        LOCK_TIMERS_READ; // must be done before TimersRecordingLock
         cMutexLock TimersRecordingLock(&TimersRecording);
         cRecDoneTimerObj *tiR = TimersRecording.First();
         while (tiR) {
-            // check if timer still exists
+            // check if a timer still exists
+            // if we find a timer we take its values, else from recDone
             bool found = false;
-
             for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti))
                 if (ti == tiR->timer) {
                     found = true;
                     break;
                 }
 
-            if (found && !tiR->timer->Recording()) {
-                if (tiR->recDone) {
-                    cSearchExt* search = SearchExts.GetSearchFromID(tiR->recDone->searchID);
-                    if (!search) return;
-                    // check if recording has ended before timer end
+            if (!tiR->recDone) { // should not happen
+                LogFile.Log(1, "recdone: found tiR without recDone struct");
+                tiR = TimersRecording.Next(tiR);
+                continue;
+            }
 
-                    bool complete = true;
+            if (found && tiR->timer->Recording()) {
+                LogFile.Log(2, "recdone: tiR for %s is recording",tiR->recDone->fileName);
+                tiR = TimersRecording.Next(tiR);
+                continue;
+            }
+
+            LogFile.Log(2, "recdone: processing tiR for %s",tiR->recDone->fileName);
+            if (strcmp(tiR->recDone->fileName,m_filename) == 0) {
+                // we have the correct entry for the check
+                bool complete = true;
+                cSearchExt* search = SearchExts.GetSearchFromID(tiR->recDone->searchID);
+                int recFraction = 100;
+                time_t stopTime = found ? tiR->timer->StopTime() : tiR->recDone->timerStop;
+
+                if (tiR->lastBreak == -1 || !search) { // started too late or missing searchID
+                    LogFile.Log(2, "started too late : '%s' or missing searchID %d", found?tiR->timer->File():m_filename, tiR->recDone->searchID);
+                    tiR->lastBreak = 0; // triggers deletion
+                }
+                else {
+                    // check if recording length is as expected
                     const cRecording *pRecording;
                     {
                         LOCK_RECORDINGS_READ;
                         pRecording = Recordings->GetByName(m_filename);
+                        long timerLengthSecs = found ? tiR->timer->StopTime() - tiR->timer->StartTime() : tiR->recDone->timerStop - tiR->recDone->timerStart;
+                        int recLen = 0;
+                        if (pRecording && timerLengthSecs) {
+                            recLen = RecLengthInSecs(pRecording);
+                            recFraction = double(recLen) * 100 / timerLengthSecs;
+                        }
                     }
-                    long timerLengthSecs = tiR->timer->StopTime() - tiR->timer->StartTime();
-                    int recFraction = 100;
-                    if (pRecording && timerLengthSecs) {
-                        int recLen = RecLengthInSecs(pRecording);
-                        recFraction = double(recLen) * 100 / timerLengthSecs;
-                    }
-                    bool vpsUsed = tiR->timer->HasFlags(tfVps) && tiR->timer->Event() && tiR->timer->Event()->Vps();
-                    if ((!vpsUsed && now < tiR->timer->StopTime()) || recFraction < (vpsUsed ? 90 : 98)) { // assure timer has reached its end or at least 98% were recorded
+                    bool vpsUsed = found ? tiR->timer->HasFlags(tfVps) && tiR->timer->Event() && tiR->timer->Event()->Vps():tiR->recDone->vpsused; 
+                    if ((!vpsUsed && now < stopTime) || recFraction < (vpsUsed ? 90 : 98)) { // assure timer has reached its end or at least 98% were recorded
                         complete = false;
-                        LogFile.Log(1, "finished: '%s' (not complete! - recorded only %d%%); search timer: '%s'; VPS used: %s", tiR->timer->File(), recFraction, search->search, vpsUsed ? "Yes" : "No");
+                        LogFile.Log(1, "finished: '%s' (not complete! - recorded only %d%%); search timer: '%s'; VPS used: %s", found?tiR->timer->File():m_filename, recFraction, search->search, vpsUsed ? "Yes" : "No");
+                        dsyslog("epgsearch: finished: '%s' (not complete! - recorded only %d%%); search timer: '%s'; VPS used: %s", found?tiR->timer->File():m_filename, recFraction, search->search, vpsUsed ? "Yes" : "No");
                     } else {
-                        LogFile.Log(1, "finished: '%s'; search timer: '%s'; VPS used: %s", tiR->timer->File(), search->search, vpsUsed ? "Yes" : "No");
-                        if (recFraction < 100)
+                        LogFile.Log(1, "finished: '%s' (complete); search timer: '%s'; VPS used: %s", found?tiR->timer->File():m_filename, search->search, vpsUsed ? "Yes" : "No");
+                        if (recFraction < 100) {
                             LogFile.Log(2, "recorded %d%%'", recFraction);
+                            dsyslog("epgsearch: finished: '%s' (complete) recorded %d%%", found?tiR->timer->File():m_filename, (recFraction<100) ? recFraction : 100);
+                        }
+                        else
+                            dsyslog("epgsearch: finished: '%s' (complete)", found?tiR->timer->File():m_filename);
                     }
-                    if (complete) {
+                    if (complete) { // add to epgsearchdone.data
                         RecsDone.Add(tiR->recDone);
                         LogFile.Log(1, "added rec done for '%s~%s';%s", tiR->recDone->title ? tiR->recDone->title : "unknown title",
                                     tiR->recDone->shortText ? tiR->recDone->shortText : "unknown subtitle",
                                     search->search);
                         RecsDone.Save();
-                        tiR->recDone = NULL; // prevent deletion
+                        tiR->recDone = NULL; // prevent deletion (now in RecsDone)
                         tiR->lastBreak = 0;
 
                         // check for search timers to delete automatically
@@ -139,28 +164,26 @@ void cRecdoneThread::Action(void)
                         // trigger a search timer update (skip running events)
                         search->skipRunningEvents = true;
                         updateForced = 1;
-                    } else if (tiR->lastBreak == 0) // store first break
+                    } else if (tiR->lastBreak == 0) // not complete: assure break is set
                         tiR->lastBreak = now;
                 }
-                if (tiR->lastBreak == 0 || (now - tiR->lastBreak) > ALLOWED_BREAK_INSECS) {
-                    // remove finished recordings or those with an unallowed break
-                    if (tiR->recDone) delete tiR->recDone; // clean up
-                    cRecDoneTimerObj *tiRNext = TimersRecording.Next(tiR);
-                    TimersRecording.Del(tiR);
-                    tiR = tiRNext;
-                    continue;
+            } // handled only tiR with correct filename
+            // cleanup
+            if (!tiR->lastBreak || (now - tiR->lastBreak) > ALLOWED_BREAK_INSECS) {
+                // remove finished recordings or those with an unallowed break
+                if (tiR->recDone) { // if added to searchdone recDone is NULL
+                  LogFile.Log(2, "recdone: remove tiR and recdone for %s", tiR->recDone->fileName);
+                  delete tiR->recDone; // clean up
                 }
-                break;
-            }
-            if (!found) {
-                if (tiR->recDone) delete tiR->recDone; // clean up
                 cRecDoneTimerObj *tiRNext = TimersRecording.Next(tiR);
                 TimersRecording.Del(tiR);
                 tiR = tiRNext;
+                LogFile.Log(2, "recdone: continue with next TiR");
                 continue;
             }
             tiR = TimersRecording.Next(tiR);
-        }
+            LogFile.Log(2, "recdone: continue without cleanup with next TiR");
+        } // while tiR
         m_fnames.erase(it);
     } // while fnames
     LogFile.Log(1, "recdone_thread ended");
diff --git a/recstatus.c b/recstatus.c
index 408f159..366b0fc 100644
--- a/recstatus.c
+++ b/recstatus.c
@@ -47,12 +47,12 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
         if (EPGSearchConfig.checkTimerConflOnRecording)
             cConflictCheckThread::Init((cPluginEpgsearch*)cPluginManager::GetPlugin("epgsearch"), true);
 
-        LOCK_TIMERS_READ;
+        LOCK_TIMERS_READ; // might be already set (thread is vdr-main)
         for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti))
             if (ti->Recording()) {
                 // check if this is a new entry
                 cRecDoneTimerObj *tiRFound = NULL;
-                cMutexLock TimersRecordingLock(&TimersRecording);
+                cMutexLock TimersRecordingLock(&TimersRecording); // always lock after TIMERS
                 for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR))
                     if (tiR->timer == ti) {
                         tiRFound = tiR;
@@ -61,7 +61,7 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
 
                 if (tiRFound) { // already handled, perhaps a resume
                     if (tiRFound->lastBreak > 0 && now - tiRFound->lastBreak <= ALLOWED_BREAK_INSECS) {
-                        LogFile.Log(1, "accepting resume of '%s' on device %d", Name, Device->CardIndex());
+                        LogFile.Log(1, "assuming resume of '%s' on device %d", Name, Device->CardIndex());
                         tiRFound->lastBreak = 0;
                     }
                     continue;
@@ -69,29 +69,41 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
 
                 cRecDoneTimerObj* timerObj = new cRecDoneTimerObj(ti, Device->DeviceNumber());
                 TimersRecording.Add(timerObj);
+                LogFile.Log(2, "created new tiR");
 
+                // ignore if not avoid repeats and no auto-delete
                 cSearchExt* search = TriggeredFromSearchTimer(ti);
-                if (!search || (search->avoidRepeats == 0 && search->delMode == 0)) // ignore if not avoid repeats and no auto-delete
+                if (!search || (search->avoidRepeats == 0 && search->delMode == 0)) {
+                    if (!search)
+                        LogFile.Log(2, "created new tiR without search");
+                    else
+                        LogFile.Log(2, "created new tiR but Repeats=%d delMode=%d",
+                            search->avoidRepeats, search->delMode);
                     continue;
+                }
 
                 bool vpsUsed = ti->HasFlags(tfVps) && ti->Event() && ti->Event()->Vps();
-                LogFile.Log(1, "recording started '%s' on device %d (search timer '%s'); VPS used: %s", Name, Device->CardIndex(), search->search, vpsUsed ? "Yes" : "No");
+                LogFile.Log(1, "recording started '%s' on device %d (search timer '%s'); VPS used: %s",
+                    Name, Device->CardIndex(), search->search, vpsUsed ? "Yes" : "No");
                 const cEvent* event = ti->Event();
                 if (!event) {
                     event = GetEvent(ti);
                     if (event)
-                        LogFile.Log(3, "timer had no event: assigning '%s'", event->Title());
+                        LogFile.Log(2, "timer had no event: assigning '%s'", event->Title());
                 }
                 if (!event) {
                     LogFile.Log(1, "no event for timer found! will be ignored in done list");
                     continue;
                 }
                 time_t now = time(NULL);
+                timerObj->recDone = new cRecDone(ti, event, search, Filename);
+                LogFile.Log(1, "epgsearch: created recDone for %s",Filename);
                 if (vpsUsed || now < ti->StartTime() + 60) { // allow a delay of one minute
-                    timerObj->recDone = new cRecDone(ti, event, search);
-                    return;
-                } else
+                    return; // search timer found and recDone created
+                } else {
+                    timerObj->lastBreak = -1; // mark as incomplete
                     LogFile.Log(1, "recording started too late! will be ignored");
+                }
             }
     }
 
