RE: PROBLEM: I/O system call never returns if file desc is closed in the
> At 22:35 +0100 2001-06-06, Alan Cox wrote: > > > This report describes a problem in the usage of file > > > descriptors across > >> multiple threads. When one thread closes a file descriptor, another > >> thread which waits for an I/O on that file descriptor is not notified > >> and blocks forever. > >THe I/O does not block forever, it blocks until completed. > That's still "forever" if you don't specify a timeout in the select. If you don't want to block until an operation completes, then don't ask to! > >The actual final > >closure of the object occurs when the last operation on it exits > Select is defined as to return, with the appropriate bit set, if/when > a nonblocking read/write on the file descriptor won't block. You'd > get EBADF in this case, therefore causing the select to return would > be a Good Thing. That is not quite correct. That is a good approximate definition of 'select's behavior, but it is not exact. As for your assertion that a noblocking read/write wouldn't block, that's not necessarily true. Remember, the 'close' may not have taken affect yet, since the descriptor is still in use by virtue of being selected on. > A related problem is that the second thread my be inside a blocking > read() instead of a select() call. It'd never continue. :-( Perfect. Doing this is absolutely, positively wrong and the more you are punished for it, the better. It's as wrong as calling 'free' on a chunk of memory when another thread may be usign it. It is impossible to make this work safely, as another thread could open a socket or file and get the same descriptor write before the call to 'read' is entered. There's no possible way to do this because there is no 'unlock a mutex and read' operation. > HOWEVER: IMHO it's bad design to distribute the responsibility for > file descriptors between threads. Why? That's a great design and it's absolutely essential in many cases. Suppose, for example, I have two descriptors I want to write to. If I assign one thread to each socket permanently, then I'm 100% guaranteed a context switch every time I change which socket I'm writing to, so if there's lots of small bits of data going out both of them, my performance will suck. But if I assign one thread to both socket descriptors, I'm guaranteed that one connection will stall if the the application-level send queue for the other has been swapped out to disk. Not distributing network I/O across threads dynamically is a recipe for either low performance or bursty performance. DS - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: PROBLEM: I/O system call never returns if file desc is closed in the
Alexander Viro <[EMAIL PROTECTED]> writes: > On 7 Jun 2001, Florian Weimer wrote: > > > Matthias Urlichs <[EMAIL PROTECTED]> writes: > > > > > Select is defined as to return, with the appropriate bit set, if/when > > > a nonblocking read/write on the file descriptor won't block. You'd get > > > EBADF in this case, therefore causing the select to return would be a > > > Good Thing. > > > > How do you avoid race conditions if more than one thread is creating > > file descriptors? I think you can only do that under very special > > circumstances, and it definitely requires some synchronization. > > The same way as you do it for many threads doing any allocations. There's a subtle difference: For malloc(), libc has a mutex (or whatever), but for open(), socket() etc., no locking is performed, and many libc functions create (and destroy) descriptors imlicitely. I still don't see how you can write maintainable and reliable software with asynchronous close(). For example, if some select() call returns EBADF after an asynchronous close(), you would have to scan the descriptors to find the offending one, but in the meantime, it has been reused by another thread. What do you do in this case? -- Florian Weimer[EMAIL PROTECTED] University of Stuttgart http://cert.uni-stuttgart.de/ RUS-CERT +49-711-685-5973/fax +49-711-685-5898 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: PROBLEM: I/O system call never returns if file desc is closed in the
Alexander Viro [EMAIL PROTECTED] writes: On 7 Jun 2001, Florian Weimer wrote: Matthias Urlichs [EMAIL PROTECTED] writes: Select is defined as to return, with the appropriate bit set, if/when a nonblocking read/write on the file descriptor won't block. You'd get EBADF in this case, therefore causing the select to return would be a Good Thing. How do you avoid race conditions if more than one thread is creating file descriptors? I think you can only do that under very special circumstances, and it definitely requires some synchronization. The same way as you do it for many threads doing any allocations. There's a subtle difference: For malloc(), libc has a mutex (or whatever), but for open(), socket() etc., no locking is performed, and many libc functions create (and destroy) descriptors imlicitely. I still don't see how you can write maintainable and reliable software with asynchronous close(). For example, if some select() call returns EBADF after an asynchronous close(), you would have to scan the descriptors to find the offending one, but in the meantime, it has been reused by another thread. What do you do in this case? -- Florian Weimer[EMAIL PROTECTED] University of Stuttgart http://cert.uni-stuttgart.de/ RUS-CERT +49-711-685-5973/fax +49-711-685-5898 - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
RE: PROBLEM: I/O system call never returns if file desc is closed in the
At 22:35 +0100 2001-06-06, Alan Cox wrote: This report describes a problem in the usage of file descriptors across multiple threads. When one thread closes a file descriptor, another thread which waits for an I/O on that file descriptor is not notified and blocks forever. THe I/O does not block forever, it blocks until completed. That's still forever if you don't specify a timeout in the select. If you don't want to block until an operation completes, then don't ask to! The actual final closure of the object occurs when the last operation on it exits Select is defined as to return, with the appropriate bit set, if/when a nonblocking read/write on the file descriptor won't block. You'd get EBADF in this case, therefore causing the select to return would be a Good Thing. That is not quite correct. That is a good approximate definition of 'select's behavior, but it is not exact. As for your assertion that a noblocking read/write wouldn't block, that's not necessarily true. Remember, the 'close' may not have taken affect yet, since the descriptor is still in use by virtue of being selected on. A related problem is that the second thread my be inside a blocking read() instead of a select() call. It'd never continue. :-( Perfect. Doing this is absolutely, positively wrong and the more you are punished for it, the better. It's as wrong as calling 'free' on a chunk of memory when another thread may be usign it. It is impossible to make this work safely, as another thread could open a socket or file and get the same descriptor write before the call to 'read' is entered. There's no possible way to do this because there is no 'unlock a mutex and read' operation. HOWEVER: IMHO it's bad design to distribute the responsibility for file descriptors between threads. Why? That's a great design and it's absolutely essential in many cases. Suppose, for example, I have two descriptors I want to write to. If I assign one thread to each socket permanently, then I'm 100% guaranteed a context switch every time I change which socket I'm writing to, so if there's lots of small bits of data going out both of them, my performance will suck. But if I assign one thread to both socket descriptors, I'm guaranteed that one connection will stall if the the application-level send queue for the other has been swapped out to disk. Not distributing network I/O across threads dynamically is a recipe for either low performance or bursty performance. DS - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: PROBLEM: I/O system call never returns if file desc is closed in the
Matthias Urlichs <[EMAIL PROTECTED]> writes: > Select is defined as to return, with the appropriate bit set, if/when > a nonblocking read/write on the file descriptor won't block. You'd get > EBADF in this case, therefore causing the select to return would be a > Good Thing. How do you avoid race conditions if more than one thread is creating file descriptors? I think you can only do that under very special circumstances, and it definitely requires some synchronization. -- Florian Weimer[EMAIL PROTECTED] University of Stuttgart http://cert.uni-stuttgart.de/ RUS-CERT +49-711-685-5973/fax +49-711-685-5898 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: PROBLEM: I/O system call never returns if file desc is closed in the
Matthias Urlichs [EMAIL PROTECTED] writes: Select is defined as to return, with the appropriate bit set, if/when a nonblocking read/write on the file descriptor won't block. You'd get EBADF in this case, therefore causing the select to return would be a Good Thing. How do you avoid race conditions if more than one thread is creating file descriptors? I think you can only do that under very special circumstances, and it definitely requires some synchronization. -- Florian Weimer[EMAIL PROTECTED] University of Stuttgart http://cert.uni-stuttgart.de/ RUS-CERT +49-711-685-5973/fax +49-711-685-5898 - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/