Help: shutdown(..., SHUT_WR) on TCP sockets

Sergey Organov sorganov@gmail.com
Mon May 20 15:15:00 GMT 2019


Florian Weimer <fweimer@redhat.com> writes:

> * Sergey Organov:
>
>> Florian Weimer <fweimer@redhat.com> writes:
>>
>>> * Sergey Organov:
>>>
>>>> Florian Weimer <fweimer@redhat.com> writes:
>>>>
>>>> [...]
>>>>
>>>>>> Given the above, could please somebody clarify what is the actual
>>>>>> intended behavior of shutdown(..., SHUT_WR) on GLIBC/Linux nowadays?
>>>>>
>>>>> Thanks for raising the issue.  I posted a patch to libc-alpha.
>>>>>
>>>>> What you saw is the expected behavior for the mainline Linux kernel.
>>>>> Since this is what distributions ship, I think it makes sense to
>>>>> document it.
>>>>
>>>> Thanks! While we are at this part of the manual, I've found that:
>>>>
>>>> "When you have finished using a socket, you can simply close its file
>>>>  descriptor with close; see Opening and Closing Files. If there is still
>>>>  data waiting to be transmitted over the connection, normally close tries
>>>>  to complete this transmission. You can control this behavior using the
>>>>  SO_LINGER socket option to specify a timeout period; see Socket
>>>>  Options."
>>>>
>>>> has its own problem.
>>>>
>>>> It looks like SO_LINGER is disabled by default in Linux, so "_normally_"
>>>> in "normally lose tries to complete this transmission" is probably
>>>> wrong.
>>>
>>> Good point.  Do you think that “normally close tries to deliver data to
>>> the peer in the background” captures the Linux behavior more
>>> accurately?
>>
>> I have no opinion, as I really encounter weird behavior on my system. To
>> me it looks like this part of GLIBC manual currently describes sane BSD
>> approach, while Linux simply gone wild, at least for me (I loose data on
>> program exit no matter how I do closing, and shutdown(...,SHUT_WR) only
>> makes it worse, even if I put long pause after it before exit()).
>
> Maybe it's related to the full-duplex problem I tried to describe?
>

Maybe, but honestly, I fail to see how adding 'shutdown(fd, SHUT_WR)'
anywhere before 'close(fd)' can do things worse from the POV of data
delivery to the other end.

What I observe is that either:

sleep(1);
close(fd);
exit(0);

or:

sleep(1);
shutdown(fd, SHUT_WR);
close(fd);
exit(0);

deliver all the data, while:

shutdown(fd, SHUT_WR);
sleep(1);
close(fd);
exit(0);

cuts some of the data (read() returns 0 on the other end indicating
closed socket).

Another mystery is that 'ioctl(fd, TIOCOUTQ, &v)' gives 0 in all the
above cases when put at the beginning of the above sequences[*],
indicating that there are no pended data, so there should be nothing to
loose in the first place, one way or another.

[*] TIOCOUTQ does give 1 right after 'shutdown(fd, SHUT_WR)', and
matching amount of data if I do write() something right before calling
it, so it does work as expected.

-- Sergey



More information about the Libc-help mailing list