I was right that close() can be non-blocking even on a TCP socket. It is the default.
When you specify SO_LINGER, you can also give a timeout to control how long close() blocks on a TCP socket
So there are 3 modes on a TCP socket:
- close() blocking with timeout via SO_LINGER
- close() blocking without timeout
- close() nonblocking