Skip to content

socket::shutdown with tests and documentation#40

Merged
vinniefalco merged 1 commit into
cppalliance:developfrom
vinniefalco:develop
Jan 21, 2026
Merged

socket::shutdown with tests and documentation#40
vinniefalco merged 1 commit into
cppalliance:developfrom
vinniefalco:develop

Conversation

@vinniefalco

@vinniefalco vinniefalco commented Jan 21, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added socket shutdown functionality to disable sends, receives, or both on active connections.
  • Documentation

    • Clarified read-operation error guidance and portable tests for EOF and operation-canceled conditions.
  • Tests

    • Added unit tests validating shutdown behaviors (send, receive, both, and shutdown on closed sockets).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 21, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds socket shutdown support: a public shutdown_type enum and shutdown() API on socket, interface method on socket_impl, platform implementations for epoll/IOCP, documentation tweaks for read_some() conditions, and new unit tests covering shutdown behaviors.

Changes

Cohort / File(s) Summary
Documentation
include/boost/corosio/io_stream.hpp
Updated read_some() docs: replaced capy::error::eof/operation_canceled with cond::eof/cond::canceled; expanded cond::eof description and portable test guidance.
Public API / Interface
include/boost/corosio/socket.hpp
Added enum shutdown_type { shutdown_receive, shutdown_send, shutdown_both }; added pure-virtual socket_impl::shutdown(shutdown_type) noexcept; added public socket::shutdown(shutdown_type) with docs.
Platform Backends
src/corosio/src/detail/epoll/...sockets.hpp, src/corosio/src/detail/iocp/...sockets.hpp
Implemented shutdown(shutdown_type) noexcept override in epoll_socket_impl and win_socket_impl; map enum to SHUT_*/SD_*, call native ::shutdown, return system::error_code.
Core Implementation
src/corosio/src/socket.cpp
Added socket::shutdown(shutdown_type) delegating to impl_; removed some inline comments in open()/close() (stylistic).
Tests
test/unit/socket.cpp
Added four unit tests verifying shutdown behaviors: send-shutdown EOF, receive-shutdown behavior, shutdown on closed socket (no crash), and shutdown-both with data delivery/EOF.

Sequence Diagram

sequenceDiagram
    rect rgba(240,248,255,0.5)
    participant Client
    end
    rect rgba(224,255,255,0.5)
    participant Socket as socket::shutdown()
    participant Impl as socket_impl
    participant Backend as epoll_socket_impl / win_socket_impl
    end
    rect rgba(255,250,240,0.5)
    participant OS as Kernel / WinSock
    end

    Client->>Socket: shutdown(shutdown_type)
    activate Socket
    Socket->>Impl: get().shutdown(type)
    activate Impl
    Impl->>Backend: shutdown(type) override
    activate Backend
    Backend->>Backend: map type -> SHUT_/SD_ constant
    Backend->>OS: call ::shutdown(fd, how)
    activate OS
    OS-->>Backend: success or errno/WSA error
    deactivate OS
    Backend-->>Impl: return system::error_code
    deactivate Backend
    Impl-->>Socket: return system::error_code
    deactivate Impl
    Socket-->>Client: returns (void) — error communicated via error_code
    deactivate Socket
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through headers, enums in paw,
I told the sockets what to thaw,
Epoll, IOCP — a gentle hush,
A graceful close, not a rush,
Tiny rabbit cheers for shutdowns done!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly describes the main change: adding socket::shutdown functionality along with tests and documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@cppalliance-bot

cppalliance-bot commented Jan 21, 2026

Copy link
Copy Markdown

An automated preview of the documentation is available at https://40.corosio.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-01-21 00:37:54 UTC

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@include/boost/corosio/socket.hpp`:
- Around line 305-313: The docs in the socket comment refer to capy::error::eof
but the example and API use the portable condition name; update the wording to
refer to capy::cond::eof and adjust the example accordingly (the read_some()
call belongs to the portable condition API matching io_stream::read_some).
Locate the comment around the read_some example in socket.hpp and replace any
occurrences of capy::error::eof with capy::cond::eof so the text and code
example are consistent (keep the example checking if (ec == capy::cond::eof)).

In `@src/corosio/src/detail/epoll/sockets.hpp`:
- Around line 140-151: The switch in shutdown(socket::shutdown_type what)
noexcept override leaves local variable how uninitialized for invalid enum
values; update the switch in this function (and mirror the same change in the
IOCP variant) to add a default case that returns an error (e.g., return
make_err(EINVAL)) instead of falling through, ensuring ::shutdown(fd_, how) is
only called with a valid how value.

In `@src/corosio/src/detail/iocp/sockets.hpp`:
- Around line 228-239: The switch in the shutdown(socket::shutdown_type) method
can leave 'how' uninitialized for out-of-range shutdown_type values; add a
default case in the switch inside the shutdown method(s) (the IOCP
implementation in src/corosio/src/detail/iocp/sockets.hpp and the epoll
implementation counterpart) that handles invalid values by returning an error
instead of falling through — e.g. return make_err(WSAEINVAL) on Windows (IOCP)
or return make_err(EINVAL) / appropriate errno conversion on POSIX (epoll);
reference the shutdown method, shutdown_type, internal_->native_handle(), and
the existing WSAGetLastError/SD_* usage so the guard is implemented in the same
function and platform-specific file.

In `@test/unit/socket.cpp`:
- Around line 703-706: The EOF assertion in the test after shutdown_send is too
strict: locate the assertion using b.read_some that binds auto [ec2, n2] and
replace the strict check (BOOST_TEST(ec2 == capy::cond::eof)) with a condition
that accepts either capy::cond::eof or zero bytes (e.g., BOOST_TEST((ec2 ==
capy::cond::eof) || (n2 == 0))) so it matches the robust pattern used in
testReadAfterPeerClose.

Comment thread include/boost/corosio/socket.hpp
Comment thread src/corosio/src/detail/epoll/sockets.hpp
Comment thread src/corosio/src/detail/iocp/sockets.hpp
Comment thread test/unit/socket.cpp
Comment on lines +703 to +706
// Next read should get EOF
auto [ec2, n2] = co_await b.read_some(
capy::mutable_buffer(buf, sizeof(buf)));
BOOST_TEST(ec2 == capy::cond::eof);

@coderabbitai coderabbitai Bot Jan 21, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get context around the failing assertion
sed -n '690,720p' test/unit/socket.cpp

Repository: cppalliance/corosio

Length of output: 1007


🏁 Script executed:

#!/bin/bash
# Find testReadAfterPeerClose test
rg -n "testReadAfterPeerClose" test/unit/socket.cpp -A 20 -B 2

Repository: cppalliance/corosio

Length of output: 1518


🏁 Script executed:

#!/bin/bash
# Search for EOF/eof handling patterns in read operations
rg -n "cond::eof|error::eof" --type=cpp | head -30

Repository: cppalliance/corosio

Length of output: 2573


🏁 Script executed:

#!/bin/bash
# Check how EOF is handled in different backends
rg -n "ec.*=.*eof|n.*==.*0" --type=cpp src/ | head -20

Repository: cppalliance/corosio

Length of output: 2196


🏁 Script executed:

#!/bin/bash
# Get the assertion in testReadAfterPeerClose
sed -n '420,430p' test/unit/socket.cpp

Repository: cppalliance/corosio

Length of output: 432


🏁 Script executed:

#!/bin/bash
# Find definitions of cond::eof and error::eof
rg -n "enum.*eof|error::eof|cond::eof" --type=cpp -B 2 -A 2 src/ include/ | head -40

Repository: cppalliance/corosio

Length of output: 2677


🏁 Script executed:

#!/bin/bash
# Check how cond::eof and error::eof relate to each other
rg -n "cond::eof|error::eof" --type=hpp include/ -B 1 -A 1 | head -50

Repository: cppalliance/corosio

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Find cond::eof and error::eof definitions
rg -n "cond|error" include/boost/corosio/ --type=cpp -B 1 -A 1 | grep -E "eof|namespace|enum|struct|class" | head -60

Repository: cppalliance/corosio

Length of output: 1212


🏁 Script executed:

#!/bin/bash
# Look for condition codes or error codes definitions
fd -e h -e hpp include/ | xargs rg "cond::|error::" -l

Repository: cppalliance/corosio

Length of output: 1707


🏁 Script executed:

#!/bin/bash
# Search for any file mentioning cond::eof or difference between condition and error
rg -n "cond::eof" . --type=cpp -B 3 -A 3

Repository: cppalliance/corosio

Length of output: 1916


🏁 Script executed:

#!/bin/bash
# Check socket.hpp documentation for shutdown behavior
sed -n '300,320p' include/boost/corosio/socket.hpp

Repository: cppalliance/corosio

Length of output: 766


🏁 Script executed:

#!/bin/bash
# Find where cond::eof is defined
rg -n "namespace.*cond|class.*eof|cond\s*=" include/ src/ --type=cpp

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check error codes and condition codes definitions
rg -n "error_code|condition_code" include/boost/corosio/ -A 3 | head -50

Repository: cppalliance/corosio

Length of output: 3247


🏁 Script executed:

#!/bin/bash
# Look for the definitions of cond and error namespaces/categories
find include/boost/corosio -name "*.hpp" -o -name "*.h" | xargs grep -l "cond::" | head -5

Repository: cppalliance/corosio

Length of output: 233


🏁 Script executed:

#!/bin/bash
# Get the full context of io_stream.hpp to understand cond::eof better
cat include/boost/corosio/io_stream.hpp | head -100

Repository: cppalliance/corosio

Length of output: 3730


🏁 Script executed:

#!/bin/bash
# Search for cond namespace and how it relates to error codes
find include/boost/corosio -type f | xargs rg "cond" | head -30

Repository: cppalliance/corosio

Length of output: 2570


🏁 Script executed:

#!/bin/bash
# Look for any condition code category or definition
rg -n "condition|cond" include/boost/capy --type=cpp | head -50

Repository: cppalliance/corosio

Length of output: 121


🏁 Script executed:

#!/bin/bash
# Check if there's any sys condition or condition code category defined
rg -n "struct.*cond|enum.*cond|make_error_code.*cond" . --type=cpp -B 2 -A 2 | head -50

Repository: cppalliance/corosio

Length of output: 521


🏁 Script executed:

#!/bin/bash
# Look for how cond::eof is being used/compared in the codebase
rg "cond::eof" . --type=cpp -B 5 -A 5

Repository: cppalliance/corosio

Length of output: 2521


🏁 Script executed:

#!/bin/bash
# Look for all EOF assertions in tests to see the pattern
rg "cond::eof|error::eof|n.*==.*0" test/unit/socket.cpp -B 2 -A 1

Repository: cppalliance/corosio

Length of output: 756


🏁 Script executed:

#!/bin/bash
# Check if capy::cond is defined in this repo or external
find . -name "*.hpp" -o -name "*.h" | xargs grep -l "namespace capy" | head -10

Repository: cppalliance/corosio

Length of output: 102


🏁 Script executed:

#!/bin/bash
# Look for how shutdown_send and close differ
rg -n "shutdown_send|shutdown_receive" include/boost/corosio/socket.hpp -B 5 -A 5

Repository: cppalliance/corosio

Length of output: 1275


🏁 Script executed:

#!/bin/bash
# Check if there's any code path that returns {ec={}, n=0} vs cond::eof
rg -n "ec_out.*=.*NULL|bytes_transferred.*==.*0" src/corosio/src/detail/ --type=cpp -B 3 -A 3 | head -50

Repository: cppalliance/corosio

Length of output: 1275


🏁 Script executed:

#!/bin/bash
# Check if there are any tests that explicitly verify both error::eof and cond::eof equivalence
rg "error::eof|cond::eof" test/unit/ --type=cpp -B 3 -A 3 | grep -A 3 -B 3 "BOOST_TEST"

Repository: cppalliance/corosio

Length of output: 1364


🏁 Script executed:

#!/bin/bash
# Look at the complete testShutdownSend function to understand if there's any special handling
sed -n '688,715p' test/unit/socket.cpp

Repository: cppalliance/corosio

Length of output: 951


🏁 Script executed:

#!/bin/bash
# Verify if other shutdown tests use the same assertion pattern
rg -n "testShutdown" test/unit/socket.cpp -A 30 | grep -E "testShutdown|BOOST_TEST.*eof|BOOST_TEST.*n.*=="

Repository: cppalliance/corosio

Length of output: 317


🏁 Script executed:

#!/bin/bash
# Search for where capy::cond and capy::error are defined or aliased
find . -type f \( -name "*.hpp" -o -name "*.h" -o -name "*.cpp" \) -exec grep -l "cond\|error" {} \; | grep -E "capy|corosio" | head -20

Repository: cppalliance/corosio

Length of output: 839


🏁 Script executed:

#!/bin/bash
# Look for any mapping or equivalence between cond::eof and error::eof
rg "cond|error" . --type=cpp -B 2 -A 2 | grep -E "using|typedef|==" | head -30

Repository: cppalliance/corosio

Length of output: 2294


🏁 Script executed:

#!/bin/bash
# Check testShutdownReceive and testShutdownOnClosedSocket for their EOF assertions
sed -n '716,770p' test/unit/socket.cpp | grep -E "BOOST_TEST|eof|ec"

Repository: cppalliance/corosio

Length of output: 595


🏁 Script executed:

#!/bin/bash
# Look for the actual implementation of read_some to see what it returns
rg -n "read_some.*{|co_return.*ec" src/corosio/src/detail/ --type=cpp -A 3 | head -50

Repository: cppalliance/corosio

Length of output: 183


🏁 Script executed:

#!/bin/bash
# Look for socket implementation details about read_some
rg -n "read_some" src/corosio/src/detail/ --type=cpp -A 5 | head -60

Repository: cppalliance/corosio

Length of output: 2656


🏁 Script executed:

#!/bin/bash
# Check what capy is - is it an external library?
find . -name "*.hpp" -o -name "*.h" | xargs grep "namespace capy" | head -5

Repository: cppalliance/corosio

Length of output: 119


🏁 Script executed:

#!/bin/bash
# Get full testShutdownReceive to see EOF assertions
sed -n '716,760p' test/unit/socket.cpp

Repository: cppalliance/corosio

Length of output: 1238


🏁 Script executed:

#!/bin/bash
# Look for any documentation about cond vs error in capy library
rg -n "portable|condition.*test|cond::" include/boost/corosio/ --type=cpp -B 2 -A 2 | head -80

Repository: cppalliance/corosio

Length of output: 5617


🏁 Script executed:

#!/bin/bash
# Search for capy library - is it external or in this repo?
find . -name "*.hpp" -o -name "*.h" | xargs grep -l "namespace capy" | xargs head -20

Repository: cppalliance/corosio

Length of output: 636


🏁 Script executed:

#!/bin/bash
# Look for error code category definitions to understand cond vs error equivalence
rg -n "error_category|condition_check|operator==" include/boost/corosio/ --type=cpp -B 2 -A 2 | head -60

Repository: cppalliance/corosio

Length of output: 1507


🏁 Script executed:

#!/bin/bash
# Check if there's any special handling that converts error::eof to cond::eof
rg -n "error::eof.*cond|cond::eof.*error" . --type=cpp -B 2 -A 2

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Look for any test utilities that might explain the difference
cat test/unit/socket.cpp | head -100

Repository: cppalliance/corosio

Length of output: 2397


🏁 Script executed:

#!/bin/bash
# Get the first 50 lines of test/unit/socket.cpp to see all imports
head -50 test/unit/socket.cpp

Repository: cppalliance/corosio

Length of output: 1340


🏁 Script executed:

#!/bin/bash
# Now understand the relationship - search for how capy::cond::eof and capy::error::eof relate
# Check if cond provides portable comparison operators
rg -n "cond::eof|error::eof" . --type=cpp | wc -l

Repository: cppalliance/corosio

Length of output: 65


🏁 Script executed:

#!/bin/bash
# Let me compare all three EOF test cases side by side
echo "=== testReadAfterPeerClose ===" && sed -n '403,430p' test/unit/socket.cpp
echo -e "\n=== testReadPartialEOF ===" && rg -A 20 "testReadPartialEOF" test/unit/socket.cpp | head -30
echo -e "\n=== testShutdownSend ===" && sed -n '685,710p' test/unit/socket.cpp

Repository: cppalliance/corosio

Length of output: 2853


🏁 Script executed:

#!/bin/bash
# Count how EOF is checked across all shutdown/close tests
echo "=== EOF handling patterns ===" && \
rg "testRead.*Close|testShutdown" test/unit/socket.cpp -A 25 | grep -E "testRead|testShutdown|BOOST_TEST.*ec.*eof|BOOST_TEST.*n.*==" | head -20

Repository: cppalliance/corosio

Length of output: 502


🏁 Script executed:

#!/bin/bash
# Verify what the composed read() operation does with EOF
sed -n '630,680p' test/unit/socket.cpp | grep -E "testRead|BOOST_TEST.*eof"

Repository: cppalliance/corosio

Length of output: 183


EOF assertion should accept zero bytes for robustness.
The test testReadAfterPeerClose (line 427) already accepts either error or zero bytes (ec2 || n2 == 0), but this test uses a strict check. After shutdown_send, both scenarios represent peer-initiated close and should handle EOF consistently. Consider accepting either condition:

-            BOOST_TEST(ec2 == capy::cond::eof);
+            BOOST_TEST(ec2 == capy::cond::eof || n2 == 0);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Next read should get EOF
auto [ec2, n2] = co_await b.read_some(
capy::mutable_buffer(buf, sizeof(buf)));
BOOST_TEST(ec2 == capy::cond::eof);
// Next read should get EOF
auto [ec2, n2] = co_await b.read_some(
capy::mutable_buffer(buf, sizeof(buf)));
BOOST_TEST(ec2 == capy::cond::eof || n2 == 0);
🤖 Prompt for AI Agents
In `@test/unit/socket.cpp` around lines 703 - 706, The EOF assertion in the test
after shutdown_send is too strict: locate the assertion using b.read_some that
binds auto [ec2, n2] and replace the strict check (BOOST_TEST(ec2 ==
capy::cond::eof)) with a condition that accepts either capy::cond::eof or zero
bytes (e.g., BOOST_TEST((ec2 == capy::cond::eof) || (n2 == 0))) so it matches
the robust pattern used in testReadAfterPeerClose.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it should not accept zero bytes, that would be a postcondition violation. The contract says eof.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vinniefalco, thank you for the clarification. You're absolutely right—I was incorrect. The contract for shutdown_send requires that an explicit EOF error code (capy::cond::eof) be returned, not just zero bytes. The test is correct as written.

The difference between shutdown() and close() is important here: shutdown() has a stricter postcondition that guarantees an EOF error code, while close() may signal EOF either through an error code or zero bytes (which is why testReadAfterPeerClose uses the more permissive ec2 || n2 == 0 pattern).


✏️ Learnings added
Learnt from: vinniefalco
Repo: cppalliance/corosio PR: 40
File: test/unit/socket.cpp:703-706
Timestamp: 2026-01-21T00:31:19.012Z
Learning: In boost::corosio, `socket::shutdown(shutdown_send)` has a contract that requires subsequent read operations to return an explicit EOF error code (`capy::cond::eof`), not just zero bytes. This is a stricter postcondition than `socket::close()`, which may signal EOF either through an error code or by returning zero bytes.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@coderabbitai

coderabbitai Bot commented Jan 21, 2026

Copy link
Copy Markdown

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #41

coderabbitai Bot added a commit that referenced this pull request Jan 21, 2026
Docstrings generation was requested by @vinniefalco.

* #40 (comment)

The following files were modified:

* `src/corosio/src/detail/epoll/sockets.hpp`
* `src/corosio/src/detail/iocp/sockets.hpp`
* `src/corosio/src/socket.cpp`
* `test/unit/socket.cpp`

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@include/boost/corosio/socket.hpp`:
- Around line 284-323: Update the shutdown() documentation (the comment above
void shutdown(shutdown_type what)) to explicitly state that calling shutdown on
an already-closed socket is a no-op and any such call is silently ignored (no
exception or error is produced), referencing the existing tests that verify this
behavior; keep the existing examples
(shutdown_send/shutdown_receive/shutdown_both) and portable eof guidance
(read_some and capy::cond::eof) but add one short sentence clarifying the
closed-socket silent-ignore semantics so callers are not surprised.

Comment on lines +284 to +323
/** Disable sends or receives on the socket.

TCP connections are full-duplex: each direction (send and receive)
operates independently. This function allows you to close one or
both directions without destroying the socket.

@li @ref shutdown_send sends a TCP FIN packet to the peer,
signaling that you have no more data to send. You can still
receive data until the peer also closes their send direction.
This is the most common use case, typically called before
close() to ensure graceful connection termination.

@li @ref shutdown_receive disables reading on the socket. This
does NOT send anything to the peer - they are not informed
and may continue sending data. Subsequent reads will fail
or return end-of-file. Incoming data may be discarded or
buffered depending on the operating system.

@li @ref shutdown_both combines both effects: sends a FIN and
disables reading.

When the peer shuts down their send direction (sends a FIN),
subsequent read operations will complete with `capy::cond::eof`.
Use the portable condition test rather than comparing error
codes directly:

@code
auto [ec, n] = co_await sock.read_some(buffer);
if (ec == capy::cond::eof)
{
// Peer closed their send direction
}
@endcode

Any error from the underlying system call is silently discarded
because it is unlikely to be helpful.

@param what Determines what operations will no longer be allowed.
*/
void shutdown(shutdown_type what);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document shutdown() behavior when the socket is closed.
The public API silently ignores shutdown on a closed socket (see tests). That should be stated to avoid surprises.

✏️ Proposed doc tweak
     /** Disable sends or receives on the socket.
 
         TCP connections are full-duplex: each direction (send and receive)
         operates independently. This function allows you to close one or
         both directions without destroying the socket.
+
+        If the socket is not open, this function has no effect.
🤖 Prompt for AI Agents
In `@include/boost/corosio/socket.hpp` around lines 284 - 323, Update the
shutdown() documentation (the comment above void shutdown(shutdown_type what))
to explicitly state that calling shutdown on an already-closed socket is a no-op
and any such call is silently ignored (no exception or error is produced),
referencing the existing tests that verify this behavior; keep the existing
examples (shutdown_send/shutdown_receive/shutdown_both) and portable eof
guidance (read_some and capy::cond::eof) but add one short sentence clarifying
the closed-socket silent-ignore semantics so callers are not surprised.

@vinniefalco vinniefalco merged commit 91ce497 into cppalliance:develop Jan 21, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants