> You are now introducing some weirdness into our little blocking world. > Threads and other scary stuff. Yes, if a gremlin reads the data from the > buffer between calls to select() and read(), the read() call > might block. > But if we assume that there is only one process with single thread using > the socket, isn't it a valid assumption that if at some point during the > select() call the data appeared in the buffer, there was *no way* for it > to disappear from the buffer without us calling read()?
No. That you cannot think of a way does not mean that no way exists. People thought that if they got a write hit from select, they could then call write without blocking. Oops, if the write was too big, they blocked. They couldn't think of a way, but they were not *guaranteed* there was no way. (And there are lots of ways this breaks on non-standard implementations too, like systems with small buffers when the other side shrinks the window.) People thought that if they got a read hit on a listening socket, they could then call accept without blocking. Oops, if the connection terminated before they called accept, they blocked. They couldn't think of a way, but they were not *guaranteed* there was no way. This is how subtle bugs and corner cases bite you on the ass. You assume that because you can think of no way to break something, it is guaranteed to work. That's not how it works. It's guaranteed to work if the relevent standard provides such a guarantee. Now, you could have a guarantee and it still not work due to thinks like bugs or trade-offs that technically violate the standard but where someone thinks that's not so important. But this weighs even more strongly in favor of my point. It is trivial to avoid these bugs and corner cases by selecting non-blocking behavior. > As for your example with write() -- of course a write of 20Mb might > block, but we are not talking about write(), we are talking about > read(). > They do have different semantics. Same goes to your mentions of accept(). Only because people *discovered* that they do. How can you say nobody will later discover this about 'read'? Say someone adds an extension to TCP to allow one side to 'revoke' data that has not been read yet by the other side. Are you going to argue that they cannot do this? Or that POSIX prohibits it? Suppose we are using SSL over a protocol that has sophisticated timeout detection. It detects a timeout and indicates that at that instant a read will not block (reporting connection close). But then, just before we call read, it gets the data it was waiting for. It then decides the connection does not need to be closed since the close was never received or acknowledged by the application. Now the read blocks. Are you saying such a protocol cannot exist? Or that 'select' cannot work with such a protocol? Or that OpenSSL should break on such a protocol? This same argument would apply to any protocol that can report non-fatal errors. You think POSIX designed 'poll' and 'select' to make non-fatal errors impossible? We have a method that is guaranteed to work -- making the socket non-blocking. > After bringing in threads, write() and accept() calls into this > discussion > you have to either mention signals or accept that you are out of > arguments. I mentioned threads not to argue that another thread might read the data but to show that it's impossible for select to make a subsequent operation non-blocking because there is no reliable way to pair select operations with subsequent operations. Simply put, you are guaranteed that 'read' will not block after a 'select' hit for read if and only if two things are provably the case: 1) Nothing can change of significance in-between when 'select' returns a read hit and you call read. 2) The test for an immediate return from 'read' is precisely identical for the test for a read hit from 'select'. Can you find what guarantees or assures these two factors? 'SSL_read' should have the same semantics as 'read'. For a blocking socket, it should block until data can be returned and should only be used when you are willing to block until there is such data. For a non-blocking socket, it should do at least some work if any is possible (ideally as much as is possible) and if none is possible without blocking, it should return an appropriate indication. However, it is a serious error to promote bad programming practice by pretending that you can use 'select' or 'poll' to ensure that a future operation on a blocking socket will not block. You simply cannot do this. It does not and has not ever worked. This is a case where you have a trivial way to guarantee the behavior you want, but instead you rely on a technique not guaranteed to provide the behavior you want. Surprise, you don't get the behavior you want. The solution is to fix your code -- don't keep the fact that you don't want to block a secret and you won't block. DS ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager [EMAIL PROTECTED]