Is a successful call to write(2) atomic?

Steve O'Hara-Smith steve at sohara.org
Wed Jun 16 06:26:42 UTC 2021


On Tue, 15 Jun 2021 23:03:35 -0700
"Ronald F. Guilmette" <rfg at tristatelogic.com> wrote:

> In message <20210616012606.3C77A1183464 at ary.qy>, 
> "John Levine" <johnl at iecc.com> wrote:
> 
> >It appears that Ronald F. Guilmette <rfg at tristatelogic.com> said:
> >>More to the point, if indeed each call to write() *is* "atomic"... at
> >>least in the sense that the given buffer will be treated like an
> >>indivisable whole, all of the way along its journey to some physical
> >>device... then why are users nontheless being encouraged, still, to
> >>"use some form of concurrency control"?  I mean what would be the point
> >>of that if in fact write() never busts up the hunks of data given to it
> >>into separate sub-hunks?

	Write never divides the hunks of data by position but it does by
time. It will write it in a concurrent block but not necessarily in a single
operation so other processes can read and write to the file while the write
is in progress.

	Nothing prevents other processes (forked or independent) from
writing in the same place and nothing stops other processes from finding
the end of the file while a write is partially completed and using that
point to start their own appends. Nothing guarantees the order in which
multiple processes write chunks out. Where they put it is guaranteed but
not when.

	IOW if one process writes ABC and another writes DEF both at the
end of file you might get ABCDEF but you won't get ABDCEF you might also get
ABDEF as D overwrites C or even ADCF as D overwites B and then C overwrites
E.

> >I think it depends on the device.  If I just want to write stuff to a log
> >file and not get it scrambled, this should do the trick:
> >
> >  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);
> 
> Thanks John, but as I noted earlier in this thread, if the data passed to
> write() in a single call isn't treated as an indivisible whole OR if each

	It is.

> of the (mutltiple) processes that are making the calls (using code as
> you have written above) is maintaining its own separate file pointer,

	They do.

> then it isn't 100% clear that what you suggested will actually solve
> the "garbling" problem.

	John's code will work (it is the standard solution) - provided
*every* writer uses it - without the O_APPEND you would need to put a seek
to EOF inside the locked section which is the pattern I most often wind up
with.

-- 
Steve O'Hara-Smith <steve at sohara.org>


More information about the freebsd-questions mailing list