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 1. 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 close(f); close(f2); 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 good :o) --- Dmitry