Date: Tue, 15 Jun 2021 02:55:14 -0400 From: Paul Procacci <pprocacci@gmail.com> To: "Ronald F. Guilmette" <rfg@tristatelogic.com> Cc: FreeBSD Questions <freebsd-questions@freebsd.org> Subject: Re: Is a successful call to write(2) atomic? Message-ID: <CAFbbPuh1xdoXqxjoEQHyPXVqX=KayokPgmpupEYovSHtcD4P5A@mail.gmail.com> In-Reply-To: <22223.1623737465@segfault.tristatelogic.com> References: <22223.1623737465@segfault.tristatelogic.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Jun 15, 2021 at 2:11 AM Ronald F. Guilmette <rfg@tristatelogic.com> wrote: > > Assume that a given program, "example", forks a child process (or perhaps > many such) and then each of these processes tries, in a manner that is > entirely non-sychronized with any of the others, to write blocks of data > using calls to write(2) to file descriptor 1. > > Assume further that "example" is run from the command line as follows: > > example > ordinary-disk-file > > Lastly asume that the return value for all calls to write() is diligently > checked to insure that it is never either -1 or a short write count, > and that if it ever, is, "example" will exit with a non-zero exit status > (and assume also that otherwise it will exit with a zero exit status). > > Question: Assuming that "example" runs and exits with a zero status (thus > indicating that all calls to write() completed successfully and none > returned > a short write count) then might it ever be the case that some single chunk > of data that was successfully written to "ordinary-disk-file" by a single > call to write() might be split into two or more parts in the output file, > with chunks of data that were written by other processes in the same family > possibly being interleaved between parts of that one chunk in the output > file? > > I had a long response, but decided to shorten it....I hope you don't mind. The only time atomicity is guaranteed is for pipes when the write(2) size fits in PIPE_BUF (512 bytes on my version of FreeBSD). Otherwise, it depends is really the best answer as it depends on the file system. Sometimes filesystems like ext4 require O_DIRECT to be set, in order to avoid the garbled text as you've mentioned, and even then it's limited to the number of bytes written. A suggestion; the way I've done something similar in the past..... Parent Process - Orchestrator - creates pipes handing one end of the pipe to each child. Child Process - do'ers - write whatever it intends on writing to the pipe the parent is waiting for data on. Parent process then grabs the data the child wrote, and in turn writes it to stdout (or whatever file descriptor you intend). This method, a bit more involved, ensures one writer to a file descriptor, is portable, and you can rest easy about it working on whatever latest and greatest file system someone decides to make. That's always been my understanding anyways, and I am open to being corrected. ~Paul -- __________________ :(){ :|:& };:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFbbPuh1xdoXqxjoEQHyPXVqX=KayokPgmpupEYovSHtcD4P5A>