Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def main(ctx):
],
'>=20',
docs=False,
coverage=False,
cache_dir='cache')

# macOS: generate() skips apple-clang when cxx_range='>=20' because
Expand Down
28 changes: 28 additions & 0 deletions .drone/drone.bat
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ if "%BOOST_BRANCH%" == "" (

call ci\common_install.bat

REM Clone the capy dependency into the superproject.
SET CAPY_BRANCH=develop
SET CAPY_TARGET=!BOOST_CI_TARGET_BRANCH!
if NOT "!DRONE_TARGET_BRANCH!" == "" SET CAPY_TARGET=!DRONE_TARGET_BRANCH!
if "!CAPY_TARGET!" == "master" SET CAPY_BRANCH=master
git clone -b !CAPY_BRANCH! https://github.com/cppalliance/capy.git !BOOST_ROOT!\libs\capy --depth 1

echo '==================================> COMPILE'

set B2_TARGETS=libs/!SELF!/test
Expand All @@ -55,6 +62,13 @@ SET BOOST_CI_SRC_FOLDER=%cd%

call ci\common_install.bat

REM Clone the capy dependency into the superproject.
SET CAPY_BRANCH=develop
SET CAPY_TARGET=!BOOST_CI_TARGET_BRANCH!
if NOT "!DRONE_TARGET_BRANCH!" == "" SET CAPY_TARGET=!DRONE_TARGET_BRANCH!
if "!CAPY_TARGET!" == "master" SET CAPY_BRANCH=master
git clone -b !CAPY_BRANCH! https://github.com/cppalliance/capy.git !BOOST_ROOT!\libs\capy --depth 1

echo '==================================> COMPILE'

if "!CMAKE_NO_TESTS!" == "" (
Expand Down Expand Up @@ -124,6 +138,13 @@ SET BOOST_CI_SRC_FOLDER=%cd%

call ci\common_install.bat

REM Clone the capy dependency into the superproject.
SET CAPY_BRANCH=develop
SET CAPY_TARGET=!BOOST_CI_TARGET_BRANCH!
if NOT "!DRONE_TARGET_BRANCH!" == "" SET CAPY_TARGET=!DRONE_TARGET_BRANCH!
if "!CAPY_TARGET!" == "master" SET CAPY_BRANCH=master
git clone -b !CAPY_BRANCH! https://github.com/cppalliance/capy.git !BOOST_ROOT!\libs\capy --depth 1

echo '==================================> COMPILE'

if "!CMAKE_NO_TESTS!" == "" (
Expand Down Expand Up @@ -160,6 +181,13 @@ SET BOOST_CI_SRC_FOLDER=%cd%

call ci\common_install.bat

REM Clone the capy dependency into the superproject.
SET CAPY_BRANCH=develop
SET CAPY_TARGET=!BOOST_CI_TARGET_BRANCH!
if NOT "!DRONE_TARGET_BRANCH!" == "" SET CAPY_TARGET=!DRONE_TARGET_BRANCH!
if "!CAPY_TARGET!" == "master" SET CAPY_BRANCH=master
git clone -b !CAPY_BRANCH! https://github.com/cppalliance/capy.git !BOOST_ROOT!\libs\capy --depth 1

echo '==================================> COMPILE'

if "!CMAKE_NO_TESTS!" == "" (
Expand Down
8 changes: 8 additions & 0 deletions .drone/drone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ common_install () {
export BOOST_CI_SRC_FOLDER=$(pwd)

. ./ci/common_install.sh

# Clone the capy dependency into the superproject.
CAPY_BRANCH=develop
CAPY_TARGET="${DRONE_TARGET_BRANCH:-$TRAVIS_BRANCH}"
if [ "$CAPY_TARGET" = "master" ]; then
CAPY_BRANCH=master
fi
git clone -b "$CAPY_BRANCH" https://github.com/cppalliance/capy.git "$BOOST_ROOT/libs/capy" --depth 1
}

if [[ $(uname) == "Linux" && "$B2_ASAN" == "1" ]]; then
Expand Down
82 changes: 48 additions & 34 deletions cmake/CorosioBuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
# Resolve all build dependencies: sibling Boost libraries when inside a
# boost tree, Capy via find_package / FetchContent, and Threads.
#
# Must be a macro so find_package results (e.g. boost_capy_FOUND) propagate
# to the caller's scope for install logic.
# Must be a macro so find_package results propagate to the caller's scope.
macro(corosio_resolve_deps)
# Sibling Boost libraries when building standalone inside a boost tree.
# The Boost::asio reference must stay out of CMakeLists.txt because the
Expand Down Expand Up @@ -187,9 +186,8 @@ function(corosio_install)
TARGETS ${_corosio_install_targets}
VERSION ${BOOST_SUPERPROJECT_VERSION}
HEADER_DIRECTORY include)
elseif(boost_capy_FOUND)
elseif(BOOST_COROSIO_IS_ROOT)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

# Set INSTALL_INTERFACE for standalone installs (boost_install handles
# this for superproject builds, including versioned-layout paths)
Expand All @@ -198,36 +196,52 @@ function(corosio_install)
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
endforeach()

set(BOOST_COROSIO_INSTALL_CMAKEDIR
${CMAKE_INSTALL_LIBDIR}/cmake/boost_corosio)

install(TARGETS ${_corosio_install_targets}
EXPORT boost_corosio-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT boost_corosio-targets
NAMESPACE Boost::
DESTINATION ${BOOST_COROSIO_INSTALL_CMAKEDIR})

configure_package_config_file(
cmake/boost_corosio-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config.cmake
INSTALL_DESTINATION ${BOOST_COROSIO_INSTALL_CMAKEDIR})
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config-version.cmake
COMPATIBILITY SameMajorVersion)

set(_corosio_config_files
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config-version.cmake)
if(WolfSSL_FOUND)
list(APPEND _corosio_config_files
${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindWolfSSL.cmake)
if(boost_capy_FOUND)
# Capy from find_package (imported target): full install with
# CMake package config and export sets.
include(CMakePackageConfigHelpers)

set(BOOST_COROSIO_INSTALL_CMAKEDIR
${CMAKE_INSTALL_LIBDIR}/cmake/boost_corosio)

install(TARGETS ${_corosio_install_targets}
EXPORT boost_corosio-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT boost_corosio-targets
NAMESPACE Boost::
DESTINATION ${BOOST_COROSIO_INSTALL_CMAKEDIR})

configure_package_config_file(
cmake/boost_corosio-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config.cmake
INSTALL_DESTINATION ${BOOST_COROSIO_INSTALL_CMAKEDIR})
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config-version.cmake
COMPATIBILITY SameMajorVersion)

set(_corosio_config_files
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/boost_corosio-config-version.cmake)
if(WolfSSL_FOUND)
list(APPEND _corosio_config_files
${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindWolfSSL.cmake)
endif()
install(FILES ${_corosio_config_files}
DESTINATION ${BOOST_COROSIO_INSTALL_CMAKEDIR})
else()
# Capy from source tree (boost root or FetchContent): export sets
# can't work because capy isn't an imported target. Install the
# library and headers only.
install(TARGETS ${_corosio_install_targets}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()
install(FILES ${_corosio_config_files}
DESTINATION ${BOOST_COROSIO_INSTALL_CMAKEDIR})
endif()
endfunction()
9 changes: 9 additions & 0 deletions include/boost/corosio/detail/timer_service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,12 @@ waiter_node::completion_op::operator()()
sched.work_finished();
}

// GCC 14 false-positive: inlining ~optional<stop_callback> through
// delete loses track that stop_cb_ was already .reset() above.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
Comment on lines +763 to +768
Copy link

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:

# First, check if the file exists and read the relevant sections
cd /tmp/repo 2>/dev/null || cd . || true
cat -n include/boost/corosio/detail/timer_service.hpp | sed -n '760,770p'

Repository: cppalliance/corosio

Length of output: 486


🏁 Script executed:

# Also check the second location mentioned (792-794)
cat -n include/boost/corosio/detail/timer_service.hpp | sed -n '790,800p'

Repository: cppalliance/corosio

Length of output: 394


🏁 Script executed:

# Search for any related GCC version checks and diagnostic pragmas in the file
rg -n 'GCC|__GNUC__|pragma GCC|Wmaybe-uninitialized' include/boost/corosio/detail/timer_service.hpp

Repository: cppalliance/corosio

Length of output: 354


🏁 Script executed:

# Check if GCC version checks are used elsewhere in the codebase for similar workarounds
rg -n '__GNUC__.*>=.*14' --type cpp --type hpp | head -20

Repository: cppalliance/corosio

Length of output: 90


🏁 Script executed:

# Check git history or comments around this pragma to understand the rationale
rg -B2 -A2 'GCC 14 false-positive' include/boost/corosio/detail/timer_service.hpp

Repository: cppalliance/corosio

Length of output: 242


🏁 Script executed:

# Check if there are other GCC version-specific compiler guards in the codebase
rg -n '__GNUC__' include/boost/corosio/ -A1 -B1 | grep -E '(__GNUC__|>|>=|<|<=)' | head -30

Repository: cppalliance/corosio

Length of output: 520


🏁 Script executed:

# Check if GCC < 14 also has this false positive or if it's truly GCC 14 specific
rg -n 'false.positive|false-positive|workaround' include/boost/corosio/ | grep -i gcc

Repository: cppalliance/corosio

Length of output: 181


Narrow the suppression to GCC 14+ to match the stated rationale.

At lines 765 and 792, the guard currently applies to all GCC versions, but the comment explicitly states this is a "GCC 14 false positive." This can suppress legitimate -Wmaybe-uninitialized warnings on older GCC releases that may not exhibit the false positive.

Proposed patch
-#if defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 14)
 `#pragma` GCC diagnostic push
 `#pragma` GCC diagnostic ignored "-Wmaybe-uninitialized"
 `#endif`
@@
-#if defined(__GNUC__) && !defined(__clang__)
+#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 14)
 `#pragma` GCC diagnostic pop
 `#endif`
📝 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
// GCC 14 false-positive: inlining ~optional<stop_callback> through
// delete loses track that stop_cb_ was already .reset() above.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
// GCC 14 false-positive: inlining ~optional<stop_callback> through
// delete loses track that stop_cb_ was already .reset() above.
`#if` defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 14)
`#pragma` GCC diagnostic push
`#pragma` GCC diagnostic ignored "-Wmaybe-uninitialized"
`#endif`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@include/boost/corosio/detail/timer_service.hpp` around lines 763 - 768, The
GCC diagnostic suppression is too broad; narrow it to GCC 14 and newer by
changing the preprocessor guard around the pragma lines (the block that
currently reads `#if` defined(__GNUC__) && !defined(__clang__) ... `#pragma` GCC
diagnostic ignored "-Wmaybe-uninitialized" ... `#endif`) to also test the GCC
major/minor version (e.g. defined(__GNUC__) && !defined(__clang__) && ((__GNUC__
> 14) || (__GNUC__ == 14 && __GNUC_MINOR__ >= 0))). Apply the same tightened
condition at both suppression sites near the comment about the "GCC 14
false-positive" so only GCC 14+ triggers the pragma.

inline void
waiter_node::completion_op::destroy()
{
Expand All @@ -783,6 +789,9 @@ waiter_node::completion_op::destroy()
if (h)
h.destroy();
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif

inline std::coroutine_handle<>
timer_service::implementation::wait(
Expand Down
2 changes: 2 additions & 0 deletions include/boost/corosio/io/io_timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class BOOST_COROSIO_DECL io_timer : public io_object
impl.expiry_ <= clock_type::now()))
{
ec_ = {};
token_ = {}; // match normal path so await_resume
// returns ec_, not a stale stop check
auto d = env->executor;
d.post(h);
return std::noop_coroutine();
Expand Down
32 changes: 2 additions & 30 deletions test/cmake_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,8 @@ if(BOOST_CI_INSTALL_TEST)
find_package(Boost CONFIG REQUIRED COMPONENTS corosio)
else()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

set(deps
# Low-level dependencies (order matters - these must come first)
assert
config
core
mp11
predef
static_assert
throw_exception
type_traits
winapi

# Mid-level dependencies
align
compat
optional
variant2

# Primary dependencies (corosio)
system
capy
)

foreach(dep IN LISTS deps)
add_subdirectory(../../../${dep} boostorg/${dep} EXCLUDE_FROM_ALL)
endforeach()

# Add corosio last, after all its dependencies
add_subdirectory(../.. boostorg/corosio)
set(BOOST_INCLUDE_LIBRARIES corosio)
add_subdirectory(../../../.. deps/boost EXCLUDE_FROM_ALL)
endif()

add_executable(main main.cpp)
Expand Down
5 changes: 5 additions & 0 deletions test/unit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#

file(GLOB_RECURSE PFILES CONFIGURE_DEPENDS *.cpp *.hpp)

if (NOT OpenSSL_FOUND AND NOT WolfSSL_FOUND)
list(FILTER PFILES EXCLUDE REGEX "tls_stream_stress\\.cpp$")
endif()

list(APPEND PFILES
CMakeLists.txt
Jamfile)
Expand Down
16 changes: 15 additions & 1 deletion test/unit/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ project boost/corosio/test/unit
;

# Non-TLS tests
for local f in [ glob *.cpp : openssl_stream.cpp wolfssl_stream.cpp cross_ssl_stream.cpp tls_stream.cpp ] [ glob test/*.cpp ]
for local f in [ glob *.cpp : openssl_stream.cpp wolfssl_stream.cpp cross_ssl_stream.cpp tls_stream.cpp tls_stream_stress.cpp ] [ glob test/*.cpp ]
{
run $(f) ;
}
Expand Down Expand Up @@ -50,3 +50,17 @@ run cross_ssl_stream.cpp

# TLS stream base tests (no specific TLS backend required)
run tls_stream.cpp ;

# TLS stress tests - separate targets so each builds when its backend is found
# (linking both would cause <build>no propagation to skip if either is missing)
run tls_stream_stress.cpp
: : :
<library>/boost/corosio//boost_corosio_openssl
: tls_stream_stress_openssl
;

run tls_stream_stress.cpp
: : :
<library>/boost/corosio//boost_corosio_wolfssl
: tls_stream_stress_wolfssl
;
24 changes: 16 additions & 8 deletions test/unit/test_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
#include <type_traits>
#include <vector>

// Valgrind slows execution ~10-20x; scale failsafe timeouts to avoid
// false failures when BOOST_NO_STRESS_TEST is defined.
#ifdef BOOST_NO_STRESS_TEST
inline constexpr int failsafe_scale = 20;
#else
inline constexpr int failsafe_scale = 1;
#endif

namespace boost::corosio::test {

//
Expand Down Expand Up @@ -845,7 +853,7 @@ run_tls_test_fail(

// Timer to unblock stuck handshakes (failsafe only)
timer timeout(ioc);
timeout.expires_after(std::chrono::milliseconds(200));
timeout.expires_after(std::chrono::milliseconds(200 * failsafe_scale));

// Store lambdas in named variables before invoking - anonymous lambda + immediate
// invocation pattern [...](){}() can cause capture corruption with run_async
Expand Down Expand Up @@ -995,7 +1003,7 @@ run_tls_shutdown_test(

// Failsafe timer in case of bugs
timer failsafe(ioc);
failsafe.expires_after(std::chrono::milliseconds(200));
failsafe.expires_after(std::chrono::milliseconds(200 * failsafe_scale));

auto client_shutdown = [&client, &done, &failsafe]() -> capy::task<> {
auto [ec] = co_await client.shutdown();
Expand Down Expand Up @@ -1110,7 +1118,7 @@ run_tls_truncation_test(
// Timeout to prevent deadlock
timer timeout(ioc);
// IOCP peer-close propagation can be bursty under TLS backends.
timeout.expires_after(std::chrono::milliseconds(750));
timeout.expires_after(std::chrono::milliseconds(750 * failsafe_scale));

auto client_close = [&s1, &s2]() -> capy::task<> {
// Cancel and close underlying socket without TLS shutdown (IOCP needs cancel)
Expand Down Expand Up @@ -1388,7 +1396,7 @@ run_connection_reset_test(

// Timeout protection
timer timeout(ioc);
timeout.expires_after(std::chrono::milliseconds(200));
timeout.expires_after(std::chrono::milliseconds(200 * failsafe_scale));

auto client_task = [&client, &client_failed, &timeout]() -> capy::task<> {
auto [ec] = co_await client.handshake(
Expand Down Expand Up @@ -1471,7 +1479,7 @@ run_stop_token_handshake_test(
// Failsafe timeout to prevent infinite hang if cancellation doesn't work
// 2000ms allows headroom for CI with coverage instrumentation
timer failsafe(ioc);
failsafe.expires_after(std::chrono::milliseconds(2000));
failsafe.expires_after(std::chrono::milliseconds(2000 * failsafe_scale));

// Client handshake - will be cancelled while waiting for ServerHello
auto client_task = [&client, &client_got_error,
Expand Down Expand Up @@ -1573,7 +1581,7 @@ run_stop_token_read_test(

// Failsafe timeout - 2000ms allows headroom for CI with coverage instrumentation
timer failsafe(ioc);
failsafe.expires_after(std::chrono::milliseconds(2000));
failsafe.expires_after(std::chrono::milliseconds(2000 * failsafe_scale));

auto client_read = [&client, &read_got_error, &failsafe]() -> capy::task<> {
char buf[32];
Expand Down Expand Up @@ -1676,7 +1684,7 @@ run_stop_token_write_test(

// Failsafe timeout - 2000ms allows headroom for CI with coverage instrumentation
timer failsafe(ioc);
failsafe.expires_after(std::chrono::milliseconds(2000));
failsafe.expires_after(std::chrono::milliseconds(2000 * failsafe_scale));

auto client_write = [&client, &large_buf, &write_got_error,
&failsafe]() -> capy::task<> {
Expand Down Expand Up @@ -1767,7 +1775,7 @@ run_socket_cancel_test(

// Failsafe timeout - 2000ms allows headroom for CI with coverage instrumentation
timer failsafe(ioc);
failsafe.expires_after(std::chrono::milliseconds(2000));
failsafe.expires_after(std::chrono::milliseconds(2000 * failsafe_scale));

// Client starts handshake - will be cancelled
auto client_task = [&client, &client_got_error,
Expand Down
Loading