Page MenuHomeFreeBSD

Make shutdown() return ENOTCONN as required by POSIX, part deux.
AbandonedPublic

Authored by ed on Jul 9 2015, 2:38 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Mar 29, 4:34 AM
Unknown Object (File)
Thu, Mar 21, 3:20 AM
Unknown Object (File)
Thu, Mar 21, 3:20 AM
Unknown Object (File)
Feb 11 2024, 5:04 PM
Unknown Object (File)
Dec 24 2023, 6:49 PM
Unknown Object (File)
Dec 22 2023, 9:54 PM
Unknown Object (File)
Dec 21 2023, 4:51 PM
Unknown Object (File)
Nov 26 2023, 1:56 PM
Subscribers

Details

Summary

Back in 2005, maxim@ attempted to fix shutdown() to return ENOTCONN in case the socket was not connected (r150152). This had to be rolled back (r150155), as it broke some of the existing programs that depend on this behavior. I reapplied this change on my system and indeed, syslogd failed to start up. I fixed this back in February (279016) and MFC'ed it to the supported stable branches. Apart from that, things seem to work out all right.

Since at least Linux and Mac OS X do the right thing, I'd like to go ahead and give this another try. To keep old copies of syslogd working, only start returning ENOTCONN for recent binaries.

I took a look at the XNU sources and they seem to test against both SS_ISCONNECTED, SS_ISCONNECTING and SS_ISDISCONNECTING, instead of just SS_ISCONNECTED. That seams reasonable, so let's do the same.

Test Plan

This issue was uncovered while writing tests for shutdown() in CloudABI:

https://github.com/NuxiNL/cloudlibc/blob/master/src/libc/sys/socket/shutdown_test.c#L26

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

ed retitled this revision from to Make shutdown() return ENOTCONN as required by POSIX, part deux..
ed updated this object.
ed edited the test plan for this revision. (Show Details)
ed added reviewers: network, gnn.
ed set the repository for this revision to rS FreeBSD src repository - subversion.

Introduction of a new syscall seems like a waste.

One can check p_osrel instead which may turn out to be sufficient. Since head's syslogd was updated some time ago, it may be fine enough to test against the latest __FreeBSD_version (or we can spare one just as a marker for this check introduction).

I can't comment on error checking itself.

ed updated this object.
In D3039#60038, @mjg wrote:

One can check p_osrel instead which may turn out to be sufficient. Since head's syslogd was updated some time ago, it may be fine enough to test against the latest __FreeBSD_version (or we can spare one just as a marker for this check introduction).

Wow. That's a nifty feature. That looks a whole lot better. I've updated the change to match against the latest __FreeBSD_version. I think it's not worth increasing, for the reason that it is possible to write code that supports both systems without any explicit checking.

Also update the manual page to reflect the changes to the behaviour.

The new behaviour appears to be POSIXly correct. POSIX shutdown spec

gnn edited edge metadata.
This revision is now accepted and ready to land.Jul 27 2015, 1:16 PM
This revision was automatically updated to reflect the committed changes.
sobomax added a subscriber: sobomax.

I think Ed's comparison with other OSes here and in the relevant differential was not entirely correct. What linux does (tested with 4.4.0) when UDP socket is shut down is actually shutting down receiving end, so any threads that are blocked in recv() on that socket return. Still shutdown() system call itself returns ENOTCONN. FreeBSD on the other hand does not do anything for the socket, so that the threads just hang. I am pretty sure there are at least some software out there that relies on that behavior, at least in our case we do. Bumped into this after upgrading to the 11.0.

Therefore, I am curious about possibility to make our behavior match that of Linux's, so we are not the odd one with regards to this, that is return an error but still shutdown the socket?

Small test case is attached. Both FreeBSD 10.3 and Linux 4.4.0 pass (albeit Linux's shutdown() returns with an error), FreeBSD 11.0 fails.

This revision is now accepted and ready to land.Apr 10 2017, 2:52 PM
sobomax requested changes to this revision.Apr 10 2017, 2:54 PM
This revision now requires changes to proceed.Apr 10 2017, 2:54 PM

Note that this is not the complete story: There's a separate issue with "interrupting" threads already blocked in I/O on sockets at shutdown(2) time. Lack of that support causes a test failure in the Java test suite (if I recall) because calling shutdown(2) on a socket from one thread while another thread is blocked in read(2)/recv(2) or write(2)/send(2) will not interrupt the blocked thread. This is due to the way we do locking and reference counting on file descriptors and sockets.