Udo Richter wrote:
Hi list,
Based on a first patch by Helmut Auer, here's a patch to solve the shutdown on running timers issue. I did some simple tests and it seemed to work, however the patch is still experimental.
The patch basically disables the offending timers up to MinEventPause minutes in the future. There's also some endless loop detection that imho should be impossible to trigger.
Some issues:
- If you decide to cancel the shutdown after confirming it first, timers
will remain disabled. Thats probably not what the user expects.
- Disabling pending timers up to MinEventPause may not what the user
expects either. I have set MinEventPause to 11 minutes (5 for shutdown, 5 for wakeup, 1 to avoid race conditions). But if an user has set this to 120 minutes for example, then the question "Recording in 100 minutes, shut down anyway?" doesn't sound like VDR wont wake up for it.
- A clean implementation should merge both loops into one function and
move the code into cTimers (API change!). (the two loops are required to skip negative values for "Recording in xx minutes")
Cheers,
Udo
--- vdr-1.4.1-orig/vdr.c 2006-07-25 15:48:14.000000000 +0200 +++ vdr-1.4.1/vdr.c 2006-07-25 16:39:38.943900248 +0200 @@ -1007,6 +1007,27 @@ if (cRecordControls::Active()) { if (!Interface->Confirm(tr("Recording - shut down anyway?"))) break;
// Stop all running timers
time_t Now = time(NULL);
cTimer *timer = Timers.GetNextActiveTimer();
time_t Next = timer ? timer->StartTime() : 0;
while (timer && Next - Now < 0) {
if (timer->IsSingleEvent())
timer->ClrFlags(tfActive);
else
timer->Skip();
timer->Matches();
cTimer *nextTimer = Timers.GetNextActiveTimer();
time_t nextNext = nextTimer ? nextTimer->StartTime() : 0;
if (nextNext < Next || (nextNext == Next && nextTimer == timer)) {
esyslog("Loop detected while disabling running timers");
break;
}
Next=nextNext;
timer=nextTimer;
}
Timers.SetModified(); } if (cPluginManager::Active(tr("shut down anyway?"))) break;
@@ -1020,6 +1041,27 @@ free(buf); if (!confirm) break;
// Stop all pending timers until MinEventTimeout
time_t Now = time(NULL);
cTimer *timer = Timers.GetNextActiveTimer();
time_t Next = timer ? timer->StartTime() : 0;
while (timer && Next - Now <= Setup.MinEventTimeout * 60) {
if (timer->IsSingleEvent())
timer->ClrFlags(tfActive);
else
timer->Skip();
timer->Matches();
cTimer *nextTimer = Timers.GetNextActiveTimer();
time_t nextNext = nextTimer ? nextTimer->StartTime() : 0;
if (nextNext < Next || (nextNext == Next && nextTimer == timer)) {
esyslog("Loop detected while disabling pending timers");
break;
}
Next=nextNext;
timer=nextTimer;
}
Timers.SetModified(); } ForceShutdown = true; break;
This is getting *way* too complex for my taste.
How about this: if the user presses the "Power" key to turn off VDR, and VDR tells him/her that there is a recording going on, or a timer will hit in a few minutes, and the user still insists in shutting down VDR *now*, what could be the reason for this? IMHO the only real reason is that the user wants to do some maintenance, for which the device must be turned off (like, for instance, install some hardware or relocate it to a different place). At any rate, chances are the user will turn it on again anyway after the action that was so important that it was worth interrupting an ongoing recording is finished.
As a safety precaution, in case the user turned off VDR and ignored all the warnings, let's just tell the shutdown script to reboot it at, say, five minutes in the future (in case a recording is going on) or whenever the next timer hits after that time.
If the user doesn't want this to happen, then he/she can simply go into the Timers menu and turn timers off as desired. I don't think VDR should make that decision behind the user's back.
Klaus