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