On Thursday 17 November 2005 18:24, Gilles Chanteperdrix wrote:
> Dmitry Adamushko wrote:
> > > >As a conclusion, the behaviour that you observed with Xenomai
> > > >pipes seems consistent with that of Linux' named pipes, except
> > > >that in Linux read() returns 0, and not an error code as you
> > > >observed with Xenomai.
> > >
> > > The read() call does *not* return when you close the *same* file
> > > handle from another pthread in the same process.
> > I confirm that and as I pointed it out in my previous mail - this is not
> > how it's supposed to be.
> > I'm currently on it. More news later.
> I am not sure about that: Linux regular pipes follow the same behaviour
> (the real destruction of the file descriptor is delayed until read()
> really returns).
Ok, it's me who is a stupid uneducated zorr... I mean bozzo :o)
The reason is quite simple indeed.
The file_operations::release() is called when a <file *> object is about to be
destroyed (file * object is created for each open file). It happens when its
refference count becomes 0.
Rigth after open() the counter == 1. As one may guess, close() decrease it on
There is another entity - file_operations::flush() which is called on each
close() call. But file_operations::release() is called only when all the
references on the object have been closed.
There can be N:1 relation. Imagine, dup() or fork() make a copy of the file
descriptor and as a result - the regerence is increased appropriately.
Now what happens is that read/write() calls increase the counter before using
a file object and decrease it right before returning.
thread1::open() --> file_operations::open() == xnpipe_open() ---> counter=1
thread1::read() --> ... counter=2 .. -> file_operations::read() ==
xnpipe_read() - blocked ... (*)
thread2::close() --> ... -> file_operations::flush() [ we don't make use of
this one in pipe.c ] --> counter = 1
So that's why xnpipe_release() is not called!
10 seconds have elapsed
thread1::read (*) - unblocked() --> copies data to the user's buffer --->
counter = 0. Oooops!
As a result -> file_operations::release() is called! Next thread1::read() call
returns an error code.
So that's what happens. We can define file_operations::flush() and wake up all
the readers there. But we can't know that this is a last reference on the
file (ok, we can actually but with a bit of hacking).
I mean :
f = open() -> 1 reference
f2 = dup(f) -> the 2-nd
2 flush() calls but only 1 release() so do we need to wake up all the readers
if the file is still valid?
So well, at least, there is no problem with the xenomai codebase, that's
Xenomai-core mailing list