[HN Gopher] The SO_LINGER page, or: why is my TCP not reliable (...
       ___________________________________________________________________
        
       The SO_LINGER page, or: why is my TCP not reliable (2009)
        
       Author : bluestreak
       Score  : 60 points
       Date   : 2021-06-12 12:49 UTC (10 hours ago)
        
 (HTM) web link (blog.netherlabs.nl)
 (TXT) w3m dump (blog.netherlabs.nl)
        
       | Animats wrote:
       | This is what we used to call a "Berkeleyism". It's an error in
       | the UC Berkeley implementation of TCP in the kernel, which, being
       | free, became standard. (Yes, there was TCP/IP before Berkeley
       | UNIX, at least four implementations.)
       | 
       | The trouble is that UNIX does not take "close()" very seriously.
       | This is because "close()" is implicit on exit, and having
       | "exit()" stall waiting for I/O is undesirable. So, close is non-
       | blocking. When you close a file after writing, close happens
       | immediately, even if writing is not yet done. "Calling close()
       | DOES NOT guarantee that contents are on the disk as the OS may
       | have deferred the writes."
       | 
       | So sockets got the same unchecked semantics as files.
       | 
       | Now, logically, you'd call "fsync()" to get a socket fully
       | flushed. But, another Berkeleyism is that sockets were originally
       | distinct from the file system, because networking was bolted on
       | as an afterthought and not well integrated. Hence "send" and
       | "recv" instead of "read" and "write". Being able to use read and
       | write on sockets came later. So, sockets have "shutdown".
        
         | throwaway09223 wrote:
         | The semantics around close() are as they are not because of
         | issues around exit, but because of shared descriptors.
         | 
         | Calls that duplicate descriptors such as fork() or dup() will
         | result in multiple descriptors which refer to the same network
         | socket. These sockets need to be able to be closed individually
         | via close() without actually shutting down the socket or
         | modifying the socket state.
         | 
         | If close() terminated a connection ala shutdown() then it would
         | be impossible for a process with a network socket to fork a
         | temporary subprocess.
         | 
         | A different call is necessary to indicate that you wish to
         | terminate the underlying network socket state.
        
           | jart wrote:
           | Usually when people criticize UNIX i/o behavior for not being
           | proper what they want is for it to do that thing NT does
           | where processes freeze indefinitely at the first sign of
           | trouble, and you have to pull out the task manager and kill
           | the thing. Nice thing about UNIX is pretty much the only time
           | things get that bad is when you implement sigchld wrong, and
           | the times when we want that behavior, like with linger, we
           | can specify the number of milliseconds it should hang. In
           | fact, NT is so zealous about the process freezing thing that
           | even when it comes to the signals it's required to be able to
           | deliver by the ANSI C standard it will spawn a thread in your
           | program just to do it. Being able to drop connections yolo
           | style without the kernel having strong opinions is pretty
           | important if, for example, your app is getting attacked by a
           | slowloris and you need to shed resources while responding to
           | requests from the main process. That's why proper operating
           | systems are rarely production worthy.
        
       | userbinator wrote:
       | _When the socket is closed as part of exit(2), it always lingers
       | in the background_
       | 
       | In other words, _not_ closing the socket before exiting might
       | actually be the easiest way to not have the connection aborted
       | with pending data?
       | 
       | Note that Windows has slightly different, and perhaps the more
       | expected, semantics for closing a socket with pending data:
       | 
       | https://docs.microsoft.com/en-us/windows/win32/api/winsock/n...
       | 
       |  _However, any data queued for transmission will be sent, if
       | possible, before the underlying socket is closed. This is also
       | called a graceful disconnect or close. In this case, the Windows
       | Sockets provider cannot release the socket and other resources
       | for an arbitrary period, thus affecting applications that expect
       | to use all available sockets. This is the default behavior for a
       | socket._
        
         | muststopmyths wrote:
         | Actually, your quoted text applies to when SO_LINGER option is
         | used and the semantics are exactly the same for both platforms
         | for this option.
         | 
         | Matching the semantics of Unix for most things was a goal of
         | Winsock. In those days the NT TCP stack was new (compared to
         | Berkeley TCP) and so there was a lot of effort spent to get it
         | to match behavior so that applications did not get unexpected
         | glitches.
        
       ___________________________________________________________________
       (page generated 2021-06-12 23:01 UTC)