On Sun, Mar 6, 2011 at 6:52 PM, Martin Steigerwald <[email protected]> wrote:
> Am Sunday 06 March 2011 schrieb Thibaut VARENE:
>> As stated before, the correct solution would be to add another layer of
>> checks during daemon startup, which would assert that the file it's
>> reading is valid (i.e. to begin with "not empty" and "has parseable
>> data"), and fall back to the backup copy otherwise. This, by design,
>> is the correct approach and has /none/ of the drawbacks of your
>> fsync() patch.
>>
>> I would gladly review such a patch.
>
> But thats at least an offer. And it would help BSD as well. Let's see what
> I will do when there will be the next rainy day during my holidays in
> Sevilla.
>
> But until then I likely have a version that works and I will fork it that
> way as long as it serves the purpose of keeping my uptime records data
> safe in a easy and simple way. This is likely to fix the issue *now*, not
> somewhen in the future. And at least I have done something efficient about
> it in the time I had at my hand.
w/e
Here's an ugly half-cooked, built but otherwise TOTALLY UNTESTED
braindump patch that tries to implement The Right Thing (tm).
Would you be kind enough to test it? I don't crash my systems as often
as you do, and they're setup in a way that apparently makes it
impossible for me to reproduce this bug.
--
Thibaut VARENE
http://www.parisc-linux.org/~varenet/
diff -Nru uptimed-0.3.16.orig/libuptimed/urec.c uptimed-0.3.16/libuptimed/urec.c
--- uptimed-0.3.16.orig/libuptimed/urec.c 2009-01-02 00:46:00.000000000 +0100
+++ uptimed-0.3.16/libuptimed/urec.c 2011-03-06 21:01:28.000000000 +0100
@@ -215,20 +215,46 @@
time_t utime, btime;
long l_utime, l_btime;
char buf[256], sys[SYSMAX+1];
+ struct stat filestat, filestatold;
+ int useold = 0;
- f = fopen(FILE_RECORDS, "r");
- if (!f) {
- f = fopen(FILE_RECORDS".old", "r");
- if (!f) return;
+ if (stat(FILE_RECORDS, &filestat))
+ useold = 1;
+ if (stat(FILE_RECORDS".old", &filestatold))
+ useold = -1;
+
+ /* assume that backupdb larger than normal db means normal is corrupted */
+ if (!useold && (filestat.st_size <= filestatold.st_size))
+ useold = 1;
- printf("uptimed: reading from backup database %s.old\n", FILE_RECORDS);
+dbtry:
+ switch (useold) {
+ case 0:
+ f = fopen(FILE_RECORDS, "r");
+ break;
+ case 1:
+ f = fopen(FILE_RECORDS".old", "r");
+ printf("uptimed: reading from backup database %s.old\n", FILE_RECORDS);
+ break;
+ default:
+ /* this should probably terminate uptimed somehow */
+ printf("uptimed: no useable database found.\n");
+ return;
+ }
+
+ if (!f) {
+ printf("uptimed: error opening database for reading.\n");
+ return;
}
fgets(str, sizeof(str), f);
while (!feof(f)) {
/* Check for validity of input string. */
if (sscanf(str, "%ld:%ld:%[^]\n]", &l_utime, &l_btime, buf) != 3) {
- /* Skip this entry. Do we want feedback here? */
+ /* database is corrupted */
+ fclose(f);
+ useold++;
+ goto dbtry;
} else {
utime = (time_t)l_utime;
btime = (time_t)l_btime;
diff -Nru uptimed-0.3.16.orig/libuptimed/urec.h uptimed-0.3.16/libuptimed/urec.h
--- uptimed-0.3.16.orig/libuptimed/urec.h 2009-01-02 00:46:00.000000000 +0100
+++ uptimed-0.3.16/libuptimed/urec.h 2011-03-06 20:48:49.000000000 +0100
@@ -21,6 +21,7 @@
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
+#include <sys/stat.h>
#ifdef PLATFORM_LINUX
#include <sys/sysinfo.h>