[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
>Exactly, I have just found out that and posted actually a long mail just >before getting this mail from you :o) > >Yep, and before getting blocked, read() increments the counter as well, that's >why we don't have a xnpipe_realease() called as a result of close(). >So everything is correct. > > Fine. Though then my problem is not related to xenomai, any suggestions on how to force read() to return? (without writing anything to the other end of the pipe)
Re: [Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
[EMAIL PROTECTED] wrote on 18.11.2005 09:57:15: > > >Exactly, I have just found out that and posted actually a long mail just > >before getting this mail from you :o) > > > >Yep, and before getting blocked, read() increments the counter as > well, that's > >why we don't have a xnpipe_realease() called as a result of close(). > >So everything is correct. > > > > > Fine. Though then my problem is not related to xenomai, any suggestions > on how to force read() to return? (without writing anything to the other > end of the pipe) ummm... send it a certain signal with pthread_kill() (and setting up something like thread::flag == END_OF_WORK_BABY at the same time but only in case when there can be other cases of getting a signal by this thread)? In such a case, read() should return -EINTR. Note, a signal handler must be installed without a SA_RESTART flag so that the read() will not be restarted after signal processing. --- Dmitry ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
>Exactly, I have just found out that and posted actually a long mail just >before getting this mail from you :o) > >Yep, and before getting blocked, read() increments the counter as well, that's >why we don't have a xnpipe_realease() called as a result of close(). >So everything is correct. > > Fine. Though then my problem is not related to xenomai, any suggestions on how to force read() to return? (without writing anything to the other end of the pipe) ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
On Thursday 17 November 2005 20:17, you wrote: > Dmitry Adamushko wrote: > > 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). > > > > My assertion was only based on the idea that nucleus::xnpipe_release() > > must be > > > > called as a result of any close() from the user space. > > If we have a look at the sources, sys_read uses fput_light and > fget_light, which increment and decrement the file descriptor > reference count (member f_count of the file structure) used by fget and > fput when the file descriptor is shared between. open and close call > fget and fput. > > "release" only get called through __fput when f_count reaches 0. Exactly, I have just found out that and posted actually a long mail just before getting this mail from you :o) Yep, and before getting blocked, read() increments the counter as well, that's why we don't have a xnpipe_realease() called as a result of close(). So everything is correct. --- Dmitry
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
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 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
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
Dmitry Adamushko wrote: > 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). > > My assertion was only based on the idea that nucleus::xnpipe_release() must > be > called as a result of any close() from the user space. If we have a look at the sources, sys_read uses fput_light and fget_light, which increment and decrement the file descriptor reference count (member f_count of the file structure) used by fget and fput when the file descriptor is shared between. open and close call fget and fput. "release" only get called through __fput when f_count reaches 0. -- Gilles Chanteperdrix.
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
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). My assertion was only based on the idea that nucleus::xnpipe_release() must be called as a result of any close() from the user space. And it, in turn, wakes up all the blocked readers. So the current implementation at least should have worked in sych a case. But, well, below is what I have observed. Maybe your assertion may explain that. The reason is actually not because of some problem in the xenomai codebase but because of the fact that nucleus::xnpipe_release() is _not_ called as I expected it to be :o) The experiment was as follows (a slightly changed klatency test): latency_module.ko uses a 10-second wait-interval for sending data int fd; // pipe thread#2 { sleep(3); close(fd); // closing a pipe. Here I expected that nucleus::xnpipe_release() would be // called as a result (== file_operations::release ). } thread#1 { fd = open(/dev/rtpN); pthread_create(thread#2); read(fd, ...); // blocked at least for 10 seconds so thread#2 closes a pipe //earlier ... if (error) break; ... close(fd); } So xnpipe_release() is _not_ called as a result of the close() call in thread#2. close() returns 0 indeed. 10 seconds after its starting, thread#1 :: read() returns a valid block of data from the latency module and right after that - an error code is returned that the pipe is no longer valid. I have taken a very brief look at the linux sources but it was not enough to get an explanation. So I'll take a closer look now :o) --- Dmitry
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
On Thursday 17 November 2005 20:17, you wrote: > Dmitry Adamushko wrote: > > 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). > > > > My assertion was only based on the idea that nucleus::xnpipe_release() > > must be > > > > called as a result of any close() from the user space. > > If we have a look at the sources, sys_read uses fput_light and > fget_light, which increment and decrement the file descriptor > reference count (member f_count of the file structure) used by fget and > fput when the file descriptor is shared between. open and close call > fget and fput. > > "release" only get called through __fput when f_count reaches 0. Exactly, I have just found out that and posted actually a long mail just before getting this mail from you :o) Yep, and before getting blocked, read() increments the counter as well, that's why we don't have a xnpipe_realease() called as a result of close(). So everything is correct. --- Dmitry ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
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 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 ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
Dmitry Adamushko wrote: > 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). > > My assertion was only based on the idea that nucleus::xnpipe_release() must > be > called as a result of any close() from the user space. If we have a look at the sources, sys_read uses fput_light and fget_light, which increment and decrement the file descriptor reference count (member f_count of the file structure) used by fget and fput when the file descriptor is shared between. open and close call fget and fput. "release" only get called through __fput when f_count reaches 0. -- Gilles Chanteperdrix. ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core
[Xenomai-core] Re: [Xenomai-help] Blocking reads from pipes
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). My assertion was only based on the idea that nucleus::xnpipe_release() must be called as a result of any close() from the user space. And it, in turn, wakes up all the blocked readers. So the current implementation at least should have worked in sych a case. But, well, below is what I have observed. Maybe your assertion may explain that. The reason is actually not because of some problem in the xenomai codebase but because of the fact that nucleus::xnpipe_release() is _not_ called as I expected it to be :o) The experiment was as follows (a slightly changed klatency test): latency_module.ko uses a 10-second wait-interval for sending data int fd; // pipe thread#2 { sleep(3); close(fd); // closing a pipe. Here I expected that nucleus::xnpipe_release() would be // called as a result (== file_operations::release ). } thread#1 { fd = open(/dev/rtpN); pthread_create(thread#2); read(fd, ...); // blocked at least for 10 seconds so thread#2 closes a pipe //earlier ... if (error) break; ... close(fd); } So xnpipe_release() is _not_ called as a result of the close() call in thread#2. close() returns 0 indeed. 10 seconds after its starting, thread#1 :: read() returns a valid block of data from the latency module and right after that - an error code is returned that the pipe is no longer valid. I have taken a very brief look at the linux sources but it was not enough to get an explanation. So I'll take a closer look now :o) --- Dmitry ___ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core