Is a successful call to write(2) atomic?

Kurt Hackenberg kh at
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
   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