Am Montag, den 04.12.2006, 02:24 +0100 schrieb Lars Lindner:
> Am Montag, den 27.11.2006, 16:50 +1100 schrieb Stewart Smith:
> > On Tue, 2006-07-18 at 20:52 +0200, Lars Lindner wrote:
> > > Am Dienstag, den 18.07.2006, 20:20 +0200 schrieb Lars Lindner:
> > > [...]
> > >
> > > I was wrong. The feed list saving code already does the temp file
> > > and renaming thing. So no problem from my point of view.
> >
> > as in:
> >
> > write to temp file
> > fsync()
> > then rename?
> >
> > a simple write and rename isn't enough (the data blocks of the file can
> > still not be written). This is POSIX compliant behaviour for the file
> > system.
> >
> > It just so happens that data=ordered journalling mode for ext3 makes
> > this problem harder to spot as it writes data blocks before the metadata
> > blocks.
>
> You are right but it is irrelevant from the Liferea point of view
> because it saves XML files using libxml2. So the write() and fsync()
> part is hidden by the library function and only the rename() is done in
> Liferea after calling the library function.
>
> The problem is this:
>
> http://bugzilla.gnome.org/show_bug.cgi?id=108329
>
> The link points to a GConf bug report from 2003 which is about missing
> error handling in libxml2. As a workaround GConf re-implements the
> libxml2 saving function including own errno handling and fsync.
>
> I had a look at the libxml2 2.6.16 source and found that it doesn't use
> fsync(). It only calls fflush() per default. From the bug report
> mentioned above it seems that application have to supply own I/O
> open/write/close callbacks to change that behaviour...
>
> I think copying the GConf2 save callback implementation could be
> a solution. I'll think over it. Did I mention that I do not like this?
Update on this. I've copied the GConf2 solution and now Liferea uses
this slightly modified function for XML saving:
gint common_save_xml(xmlDocPtr doc, gchar *filename) {
FILE *fp;
char *xmlbuf;
int fd, n;
fp = g_fopen(filename, "w");
if(NULL == fp)
return -1;
xmlDocDumpFormatMemory(doc, (xmlChar **)&xmlbuf, &n, TRUE);
if(n <= 0) {
errno = ENOMEM;
return -1;
}
if(fwrite(xmlbuf, sizeof (xmlChar), n, fp) < n) {
xmlFree (xmlbuf);
return -1;
}
xmlFree (xmlbuf);
/* flush user-space buffers */
if (fflush (fp) != 0)
return -1;
if ((fd = fileno (fp)) == -1)
return -1;
#ifdef HAVE_FSYNC
/* sync kernel-space buffers to disk */
if (fsync (fd) == -1)
return -1;
#endif
fclose(fp);
return 0;
}
File renaming is as it was before and is done outside of this function.
Will be included in 1.2-RC4 (release approx. this weekend).
Please everyone retest!!!
Lars
|