Is a successful call to write(2) atomic?
Kurt Hackenberg
kh at panix.com
Wed Jun 16 23:12:59 UTC 2021
On 2021/06/16 18:39, Ronald F. Guilmette wrote:
> The only reason I mention that is because I've just tried changing my
> code so that the FD (#1) gets O_APPEND set on it at startup time and
> then the calls to write() are wrapped in calls to flock() just as
> John Levine and others suggested. Result? Output is still garbled.
John Levine's sample code opened and closed the file around each write.
Here is that code:
fd = open("somefile", O_CREAT|O_WRONLY|O_APPEND);
/* put some stuff in buf[] */
flock(fd, LOCK_EX);
write(fd, buf, strlen(buf)): /* O_APPEND ensures it's added at the end */
flock(fd, LOCK_UN);
Since you only open the file once, you should seek to end of file before
each write, as somebody else pointed out. You should do that seek, and
the write, while holding the file lock. That is:
lock file
seek to EOF
write
unlock file
Does your code do that?
The reason, of course, is that some other process could move end of file
out from under you while you do not hold the file lock.
> The one really odd thing about all of this is that I already have, and
> have had, for a long time now, *many* programs that I've built and that
> I have been using, also for a long time, that follow this same general
> model, i.e. a parent a a lot of "worker bee" child processes where each
> of the children, after completing a work item, does itself write a single
> line of output, and *those* programs have all seemed to work flawlessly
> (i.e. no output garbling) over a long period of time.... HOWEVER they
> are all using the stdio functions to write to stdout, rather than
> calling write() directly to write to FD #1.
Those C library functions buffer the I/O operations within the user-mode
process. The system calls don't do that. That C library buffering could
change the internal details of concurrent access.
> OK, so I tried swapping out calls to write() to call to fwrite()...
>
> Result: Some output lines still garbled.
No surprise. You should lock the file, seek to end, write, unlock.
More information about the freebsd-questions
mailing list