Eli Zaretskii wrote:

> > From: Frank Heckenbach <f.heckenb...@fh-soft.de>
> > 
> > Eli Zaretskii wrote:
> > 
> > > The problem exists, but there's nothing that can be done about it, as
> > > long as we use write/fwrite/fprintf for this: the call to 'write'
> > > isn't atomic on Windows even without O_APPEND, because of the
> > > text-mode translation of newlines to CR-LF pairs.
> > 
> > I didn't mean the whole write() must be atomic, just the seek and
> > write part. I.e., if the translation is done in user-space and then
> > a system call does the write and seek atomically, it might still be
> > OK even without O_APPEND.
> 
> But that's what I'm telling you: each chunk of text after NL to CR-LF
> conversion is written separately in a separate call to WriteFile,
> which is the low-level API for file I/O.

Actually you hadn't told me this before. I had assumed the data was
converted as a whole and then written in one go. Now what you say
makes sense to me.

So the original problem (losing some output) still might not exist,
but a different problem might exist (unintended line-wise mixup of
different outputs) and might not be fixed by O_APPEND.

> > As I undestood you, you'd have to write an emulation for
> > fcntl (F_SETFD). That code has to be written and maintained, and it
> > adds a (small) runtime overhead. Not sure if that's worth saving an
> > #ifdef, *if* the problem doesn't actually exist.
> 
> Given your next message about tmpfile, I will need that anyway.

It's the same situation (just seen from the other end), so if you
don't need O_APPEND for stdout/stderr, you won't need it for the
tmpfiles either.

> > > > > I wasn't talking about synchronization or merging.  I was talking
> > > > > about _losing_ some of the output, which was the issue discussed here.
> > > > 
> > > > That's the consequence of lack of synchronization.
> > > 
> > > No, it isn't.  If the same file pointer were used, there would be no
> > > need for any synchronization, because that pointer would serialize
> > > output by its very nature.
> > 
> > Not sure what you mean here. The OS is not a magic box that does
> > anything "by its very nature".
> 
> No magic needed when there's only one file pointer, because a single
> file pointer can only be at one place at any given time.

Yes, but not necessarily at different places at different times:

> > void write (int fd, void *data, size_t size)
> > {
> >   if (getflags (fd) & O_APPEND)
> >     {
> >       lock_mutex (get_mutex (fd));
> >       off_t pos = get_size (fd);
> >       do_write (fd, pos, data, size);
> >       set_pos (fd, pos + size);
> >       unlock_mutex (get_mutex (fd));
> >     }
> >   else
> >     {
> >       // no mutex here!
> >       off_t pos = get_pos (fd);
> >       do_write (fd, pos, data, size);
> >       set_pos (fd, pos + size);
> >     }
> > }
> 
> If the 'else' clause uses a single file pointer system-wise, there's
> no overwriting because the pointer is not moved between writes.

I still can't follow you. Just imagine this function is run by two
different processes simultaneously with the same FD without
O_APPEND. Both fetch the current position (get_pos) and get the same
value. Then both write (do_write) at this same position, overwriting
each other. Finally, both update the file pointer (set_pos), but
again, only the 2nd one becomes effective.

That's a rather typical lack-of-synchronization situation, and a
mutex around the code would fix it, because one process wouldn't be
able to get_pos before the other one has finished and done set_pos.
If I was designing a system, I might have done it this way, but fact
is POSIX doesn't mandate it, so we can't assume it. But perhaps
Windows does so, and then this problem doesn't exist there.

_______________________________________________
Bug-make mailing list
Bug-make@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-make

Reply via email to