shutdown#
Shut down one direction of a socket connection, or both.
shutdown tells the kernel to stop a socket doing further reads, further
writes, or both — without closing the file descriptor. Unlike close,
the effect is immediate and propagates through every forked copy of the
descriptor, not just this process’s. HOW has the same meaning as the
argument to the shutdown(2) syscall.
Synopsis#
shutdown SOCKET, HOW
What you get back#
1 on success. On failure, undef if SOCKET is not a valid
filehandle, or 0 with $! set for any other error (the socket
is not connected, already shut down in that direction, etc.).
Two distinct failure returns, so a three-way test is sometimes warranted:
my $r = shutdown($sock, 1);
if (!defined $r) { die "bad filehandle" }
elsif (!$r) { die "shutdown failed: $!" }
The HOW argument#
HOW is a small integer matching the POSIX SHUT_* constants:
0— stop reading. The peer can still send, but data will be discarded by the kernel andread/sysreadon this end will return end-of-file.1— stop writing. Queued output is flushed, then the peer sees end-of-file on its read side.print/syswriteon this end will fail and raiseSIGPIPE.2— stop both directions. Equivalent to callingshutdownwith0and then1.
The symbolic names SHUT_RD, SHUT_WR, SHUT_RDWR live in
Socket if you prefer readable code:
use Socket qw(SHUT_WR);
shutdown $sock, SHUT_WR;
shutdown vs close#
close drops the file descriptor in the current process only.
Other processes that inherited the descriptor through fork keep their
copies open, and the peer does not see end-of-file until the last copy
is closed.
shutdown acts on the underlying socket, not on the descriptor. After
shutdown($sock, 1) every forked copy sees the write half closed and
the peer reads end-of-file right away — even though the descriptor
itself is still open and can still be read from.
That is the usual reason to reach for shutdown: a parent and child
share a socket, the child has finished sending, and the parent must
keep reading replies. close in the child would be invisible to the
peer; shutdown($sock, 1) is not.
Half-close for request/response protocols#
A client that sends a complete request and then needs the server to
know there is no more input uses shutdown with HOW = 1:
use IO::Socket::INET;
my $sock = IO::Socket::INET->new(PeerAddr => "example.com:80")
or die "connect: $!";
print $sock "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
shutdown $sock, 1; # signal end-of-request to the server
while (my $line = <$sock>) {
print $line;
}
close $sock;
Without the shutdown, servers that read until end-of-input would
block waiting for more request data.
Examples#
Stop reading but keep writing — the peer may continue to send, we just will not look at it:
shutdown $sock, 0;
Stop writing, keep reading — typical half-close after finishing a request:
shutdown $sock, 1;
Full shutdown, then close the descriptor:
shutdown $sock, 2;
close $sock;
Using Socket constants for readability:
use Socket qw(SHUT_RD SHUT_WR SHUT_RDWR);
shutdown $sock, SHUT_WR;
Check the specific error when a shutdown fails on an already-closed direction:
unless (shutdown $sock, 1) {
warn "shutdown write failed: $!";
}
Edge cases#
Writing after
shutdown($sock, 1)fails and raisesSIGPIPE. The default action terminates the process; install$SIG{PIPE} = 'IGNORE'(or a handler) to convert it into a normal write failure you can check.Reading after
shutdown($sock, 0)returns end-of-file immediately, not an error. Any data already queued in the kernel’s receive buffer is discarded.Not a socket: calling
shutdownon a regular filehandle sets$!toENOTSOCKand returns0.Not connected:
shutdownon a socket that was never connected (a freshsocketresult, or a listening socket) sets$!toENOTCONNand returns0.Double shutdown: shutting down the same half twice typically returns
0withENOTCONN. Portable code ignores the second failure rather than treating it as fatal.Closed filehandle: returns
undef; underuse warningsashutdown() on closed socketwarning is emitted.Descriptor is not closed:
shutdowndisables the directions you asked for but leaves the file descriptor open. Callclose(or let the handle go out of scope) when you are actually done with it.Shared descriptors across
fork: this is the caseshutdownis designed for. All processes holding the descriptor see the shutdown take effect immediately; they do not get separate views.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
close— release the descriptor in this process; does not affect forked copies and does not signal end-of-file to the peer until the last copy closessocket— create the socket thatshutdownoperates onconnect— establish the connection;shutdownon an unconnected socket fails withENOTCONNaccept— produces the connected socket on the server side that typically gets half-closed withshutdownSocket— exportsSHUT_RD,SHUT_WR,SHUT_RDWRand the rest of the socket-level constants$!— system error string to check after a0return