Skip to content

Fix tcp_server::bind() to not throw despite returning error_code#105

Merged
MungoG merged 1 commit intocppalliance:developfrom
MungoG:fix-bind-throw
Feb 4, 2026
Merged

Fix tcp_server::bind() to not throw despite returning error_code#105
MungoG merged 1 commit intocppalliance:developfrom
MungoG:fix-bind-throw

Conversation

@MungoG
Copy link
Contributor

@MungoG MungoG commented Feb 4, 2026

tcp_server::bind() was documented to return std::error_code but internally called the throwing tcp_acceptor::listen() overload, violating its API contract.

Add non-throwing listen() overloads to tcp_acceptor that take std::error_code& as the last parameter, following Boost.Asio conventions. The throwing overload now delegates to the non-throwing implementation.

Changes:

  • Add tcp_acceptor::listen(endpoint, std::error_code&)
  • Add tcp_acceptor::listen(endpoint, int backlog, std::error_code&)
  • Update tcp_server::bind() to use the non-throwing overload
  • Add tests for success and failure paths using TEST-NET-1 addresses
  • Add test for listen() on already-open acceptor behavior

Summary by CodeRabbit

  • Refactor
    • Improved error handling in TCP server operations by shifting from exception-based to error-code-based approach. Error codes must now be checked and are properly propagated through the network stack for better error detection and control.

@codecov
Copy link

codecov bot commented Feb 4, 2026

Codecov Report

❌ Patch coverage is 76.92308% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.42%. Comparing base (e56eb71) to head (ba7f418).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
src/corosio/src/tcp_acceptor.cpp 75.00% 1 Missing ⚠️
src/corosio/src/test/mocket.cpp 66.66% 1 Missing ⚠️
src/corosio/src/test/socket_pair.cpp 50.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #105      +/-   ##
===========================================
- Coverage    80.42%   80.42%   -0.01%     
===========================================
  Files           64       64              
  Lines         5401     5406       +5     
===========================================
+ Hits          4344     4348       +4     
- Misses        1057     1058       +1     
Files with missing lines Coverage Δ
include/boost/corosio/tcp_acceptor.hpp 94.73% <ø> (ø)
src/corosio/src/tcp_server.cpp 64.70% <100.00%> (+1.06%) ⬆️
src/corosio/src/tcp_acceptor.cpp 91.42% <75.00%> (+2.85%) ⬆️
src/corosio/src/test/mocket.cpp 72.63% <66.66%> (-0.49%) ⬇️
src/corosio/src/test/socket_pair.cpp 71.42% <50.00%> (-2.11%) ⬇️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e56eb71...ba7f418. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 4, 2026

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

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

2026-02-04 19:20:37 UTC

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 4, 2026

GCOVR code coverage report https://105.corosio.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://105.corosio.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://105.corosio.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-02-04 19:22:10 UTC

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

Warning

Rate limit exceeded

@MungoG has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 13 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

The tcp_acceptor::listen() method's error handling is refactored from exception-based to error-code-based. The method signature changes from void to [[nodiscard]] std::error_code, with updated implementations in IOCP and POSIX branches. The caller in tcp_server is updated to handle the returned error code and perform cleanup on failure.

Changes

Cohort / File(s) Summary
Error Handling Refactor
include/boost/corosio/tcp_acceptor.hpp, src/corosio/src/tcp_acceptor.cpp
Changed listen() return type from void to [[nodiscard]] std::error_code. Implementation reworked to return error codes instead of throwing exceptions; POSIX branch now returns operation_not_supported instead of throwing logic_error.
Caller Update
src/corosio/src/tcp_server.cpp
Updated tcp_server::bind() to capture and return the error code from listen(), with added cleanup logic to remove the port from internal state on listen failure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 From exceptions thrown to codes returned,
A gentler path the acceptor's learned,
No more wild throws in the dark,
Just calm errors left their mark!
Cleanup flows with grace and care,
Error codes fly through the air! 🎉

🚥 Pre-merge checks | ✅ 2
✅ 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 accurately describes the main fix: addressing a discrepancy where tcp_server::bind() was returning error_code but still throwing exceptions via tcp_acceptor::listen().

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
include/boost/corosio/tcp_acceptor.hpp (1)

192-205: ⚠️ Potential issue | 🟡 Minor

Document notable error conditions and no-throw behavior.

Now that listen() returns std::error_code, the docs should list key error conditions (e.g., operation_not_supported when no acceptor_service is present) and explicitly state the exception behavior.

✍️ Suggested doc augmentation
@@
-    `@return` An error code indicating success or the reason for failure.
-        A default-constructed error code indicates success.
+    `@return` An error code indicating success or the reason for failure.
+        A default-constructed error code indicates success.
+    
+    `@par` Error Conditions
+    - operation_not_supported: the acceptor service is unavailable in the context.
+    - errc::address_in_use, errc::permission_denied, etc., depending on bind/listen failure.
+    
+    `@throws`
+    No exceptions are thrown during normal operation.
As per coding guidelines, docstrings should include error conditions and `@throws` documentation.

tcp_server::bind() could throw because tcp_acceptor::listen() had
throwing overloads. This changes listen() to return [[nodiscard]]
std::error_code, allowing bind() to properly propagate errors without
throwing.

API change for tcp_acceptor::listen():
  Before: void listen(endpoint, int backlog = 128)        // throws
          void listen(endpoint, std::error_code&)         // out-param
          void listen(endpoint, int, std::error_code&)    // out-param

  After:  [[nodiscard]] std::error_code listen(endpoint, int backlog = 128)

The [[nodiscard]] attribute ensures callers cannot accidentally ignore
errors. This aligns with signal_set and socket options which already
use non-throwing return values.

Changes:
- Fix tcp_server::bind() to capture and return listen() error code
- Consolidate tcp_acceptor::listen() to single non-throwing overload
- Document error conditions (address_in_use, address_not_available,
  permission_denied, operation_not_supported) and @throws Nothing
- Update test utilities (socket_pair, mocket) with error checks
- Update all unit tests (~20 call sites) to check return values
- Update documentation (tcp_acceptor.adoc, tls.adoc, signals.adoc,
  endpoints.adoc) with new error-handling pattern
@MungoG MungoG merged commit ba7f418 into cppalliance:develop Feb 4, 2026
18 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