ca522703   
   From: grahn+nntp@snipabacken.se   
      
   On Fri, 2010-02-19, David Schwartz wrote:   
   > On Feb 19, 9:46 am, Rick Jones wrote:   
   >   
   >> A reasonable question - of course, HP-UX 11.X will return ENOBUFS on   
   >> the accept() call when that happens (and I ass-u-me there is no other   
   >> connection on the listen queue). No, I don't know why ENOBUFS was   
   >> chosen vs something like EAGAIN...   
   >   
   > What a strange choice. I would love to hear what their reasoning was.   
   > It doesn't even solve the OP's problem, because a reasonable thing for   
   > code to do if 'accept' returns ENOBUFS is to wait a fraction of a   
   > second and then call 'accept' again. If it does that, it will again   
   > block indefinitely even though it got a 'select' hit.   
      
   I don't know; to me the reasonble thing to do is to forget about that   
   accept, trust that the kernel cleans up any remnants of the   
   connection, and go back to select(). If the very first thing I do to   
   accept a new connection fails so badly that I don't even get a   
   descriptor for it, why should I press the issue and expect it to   
   suddenly, magically work? My time is better spent preparing to serve   
   other, probably better-behaved, clients.   
      
   On the other hand ... when I posted the question I was on a Suse Linux   
   system with weird product-differentiation man pages. The normal   
   Linux accept(2) man page says:   
      
    There may not always be a connection waiting after a SIGIO is   
    delivered or select(2) or poll(2) return a readability event   
    because the connection might have been removed by an   
    asynchronous network error or another thread before accept() is   
    called. If this happens then the call will block waiting for   
    the next connection to arrive. To ensure that accept() never   
    blocks, the passed socket sockfd needs to have the O_NONBLOCK   
    flag set (see socket(7)).   
      
   which should please DS. (I don't count "by another thread" because   
   that would be my own fault.)   
      
   > If you assume a program is written knowing about this behavior and   
   > deliberately goes back to 'select' on an ENOBUFS, why not just fix the   
   > program portably by setting the socket non-blocking? If you know you   
   > need to address the issue, why not address is that documented,   
   > portable way?   
   >   
   > Did there 'just happen to be' a lot of code that made the select/   
   > accept assumption that, by sheer luck, returned to 'select' on a   
   > ENOBUFS error?   
      
   Would it really be a lot of code to keep a "this connection was   
   stillborn" marker in the listening queue, rather than popping the   
   queue? I've never looked at a TCP implementation, but it doesn't sound   
   a lot harder. ENOBUFS may not be a good choice though.   
      
   I guess what you're really saying, DS, in a roundabout way, is that   
   blocking sockets are useless, and that anything which makes them less   
   useless is therefore a bad thing?   
      
   Now I've seen actual documentation saying you cannot call accept(2)   
   without risking blocking forever, unless the socket is O_NONBLOCK.   
      
   But (a) I don't see why it isn't always handled like Rick Jones   
   describes, and (b) I can't see it as a positive thing. For the rest   
   of the task I'm looking at, I can avoid blocking completely. It's just   
   this odd error case in the connecting phase (which I have been unable   
   to trigger in controlled experiments, by the way) which still is   
   unsafe.   
      
   /Jorgen   
      
   --   
    // Jorgen Grahn O o .   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|