I have a producer-consumer structure implemented as two separate
processes, and I'm using a directory structure to pass the data.
The producer places one file for each item, and the consumer
periodically
scans the directory with opendir and readdir.
The file is created as uid.tmp (uid meaning a unique id) while the
producer
writes the data; once done, it closes the file, and then calls
rename to
remove the .tmp at the end.
The consumer scans the directory, ignoring files with names ending in
.tmp (they will be processed during the next pass --- latency is not
a
problem in my application).
My question is: what if the consumer is scanning the directory at
the
exact same time that the producer is adding a new item?
A quick experiment suggests that opendir makes a copy of the
directory
contents in memory (I scan the directory with readdir with a 1-
second
delay between items; while it is scanning, I create a file on that
directory,
and the file does not show up in the test program output; it does
show
the next time I run it).
Is the above guaranteed behaviour? Or does it happen that way as
well as could happen some other way?
Either way: are these operations atomic? Would I be in trouble if,
say,
in an SMP or multi-core CPU system, the call to opendir or readdir
and
the creation or renaming of a new file are happening concurrently
(that
is, "truly" simultaneous)??
I would very much like to avoid having to synchronize the producer;
that is, I would like to have the producer simply place any files
whenever
it wants to, without risking being blocked/delayed due to concurrent
access from the consumer process.
Thanks for any comments!
Carlos
--
> Hi,
>
> I have a producer-consumer structure implemented as two separate
> processes, and I'm using a directory structure to pass the data.
>
> The producer places one file for each item, and the consumer
> periodically scans the directory with opendir and readdir.
>
> The file is created as uid.tmp (uid meaning a unique id) while the
> producer writes the data; once done, it closes the file, and then
> calls rename to remove the .tmp at the end.
>
> The consumer scans the directory, ignoring files with names ending in
> .tmp (they will be processed during the next pass --- latency is not a
> problem in my application).
>
> My question is: what if the consumer is scanning the directory at the
> exact same time that the producer is adding a new item?
The POSIX spec says:
If a file is removed from or added to the directory after the most
recent call to opendir() or rewinddir(), whether a subsequent call
to readdir() returns an entry for that file is unspecified.
> Either way: are these operations atomic? Would I be in trouble if,
> say, in an SMP or multi-core CPU system, the call to opendir or
> readdir and the creation or renaming of a new file are happening
> concurrently (that is, "truly" simultaneous)??
Files either exist or do not exist. There is no half-way state
visible to applications.
--
Måns Rullgård
ma...@mansr.com
The state of "open, but link count is zero" might be considered
a "half-way dead" state. Also, readlink("/proc/<pid>/fd/<n>", )
on such a file has peculiar properties.
--
>> Files either exist or do not exist. There is no half-way state
>> visible to applications.
>
> The state of "open, but link count is zero" might be considered
> a "half-way dead" state.
Fine, let's nitpick. How about "directory entries either exist or do
not exist"?
--
Måns Rullgård
ma...@mansr.com
> Fine, let's nitpick. How about "directory entries either exist or do
> not exist"?
There are a few weird things that are allowed to happen, but they are
*very* weird. You will not see things breaking or a change to one file
causing another one to disappear or to appear twice (due to some kind
of internal directory reorganization).
One example of a weird thing you might see is if you have four
unsynchronized processes and two of them create files while the other
two read the directory. For example:
A) Create 'file1'.
B) Create 'file2'.
C) Read directory
D) Read directory
It is entirely possible for 'C' to see 'file1' but not 'file2' while
'D' sees 'file2' but not 'file1'. That is, if you don't compel an
order between the two creations, you are not guaranteed that the
ordering will be consistent.
The usual synchronicity guarantee is that if you execute operations in
an unforced order, you will get results as if they happened in one of
the possible orders. You do not have a guarantee quite this strong.
No ordering of A, B, C, and D, will produce the result you might see.
DS
Just to double check --- this should not be applicable to my
situation,
right? The producer creates the file with name .tmp, puts the data,
and then calls rename to remove the .tmp from the filename; as I
recall, rename *is* atomic (though man 2 rename does not explicitly
indicate this).
If the readdir happens to give me an entry for a file with .tmp, then
I would ignore it anyway, so it wouldn't be a problem that for some
extreme coincidence, readdir got an entry that was "half-way" through
file creation.
My concern was more in the way of: would opendir or readdir fall
into some form of "undefined behaviour" (or UB-like situation) when
operating concurrently with the file creation? (as I understand
from
your replies so far, that's not an issue?)
Thanks,
Carlos
--
Yes. It refers to a file which no longer has an associated name in the
filesystem, but some processes still have an open descriptor refering
to it. This means that the file contents will remain stored in the
filesystem until the last descriptor which could potentially be used
to access them has been closed.