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

Sergey Organov sorganov@gmail.com
Mon Jul 8 14:17:00 GMT 2019


Florian Weimer <fweimer@redhat.com> writes:

> * Sergey Organov:
>
>> 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).
>
> Wait, you get less data with the last sequence?  And you do not write to
> fd after the shutdown call?

Yes, and this is single-threaded application so I'm very sure I don't
write anything myself.

However, as I already mentioned, ioctl(fd, TIOCOUTQ, &v) gives 0 before
shutdown() and 1 right  after shutdown(), that suggests shutdown()
itself writes something. Dunno if it's expected.

>
> That should definitely not happen.

I also think it should not, and I overcame it at upper-level of my
application for now, as I didn't have time to get down to kernel
internals to figure what actually happens, nor do I have enough TCP
stack knowledge to figure these things easily.

>
>> 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.
>
> Yes, I agree that data loss should not happen in these cases.

It looks like shutdown() does something that is transferred to receiver
and makes it drop some amount of recently received data that receiving
application didn't read yet. I.e., it's probably receiving end that
drops the data?

> There has to be something else that triggers an RST segment, or
> perhaps there is a middlebox with a broken TCP implementation.

As far as I recall, I did try direct cable connection from dedicated
Ethernet controller on my PC running the application under:

Linux 4.9.0-0.bpo.6-686 #1 SMP Debian 4.9.88-1+deb9u1~bpo8+1 (2018-05-13) i686 GNU/Linux

to embedded ARM/Linux board receiving the data, running Linux 4.9.x,
4.9.145 being most likely version.

If it looks like an unknown bug, I think I can resurrect the tests and
investigate further.

-- Sergey



More information about the Libc-help mailing list