diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb86c2004..d259744f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,31 +61,48 @@ jobs: strategy: matrix: compiler: - - clang-3 - - clang-6 - - clang-8 - - clang-9 - - clang-10 - - clang-11 - - clang-15 - - clang-17 - - gcc-4.8 - - gcc-5 - - gcc-6 - - gcc-7 - - gcc-8 - - gcc-11 - # - gcc-13 TODO: figure out why its not passing + - name: clang-3 + - name: clang-6 + - name: clang-8 + - name: clang-9 + - name: clang-10 + - name: clang-11 + - name: clang-15 + - name: clang-17 + - name: gcc-4.8 + - name: gcc-5 + - name: gcc-6 + - name: gcc-7 + - name: gcc-8 + - name: gcc-11 + - name: gcc-13 + # See Issue: https://github.com/llvm/llvm-project/issues/59007. Although this issue + # has been fixed in LLVM, the fix will probably not propagate to older versions of Ubuntu and GCC 13.1. + # + # Starting with GLIBC version 2.34, the `dn_expand` function, previously found in `libresolv.so`, was moved to `libc.so`. This + # function is used internally by the `getaddrinfo()` system call. + # + # In our setup (As of December 2024), we are using an Ubuntu 18 Docker image on a newer Ubuntu host. + # However, due to compatibility issues between newer libasan.so in GCC 13.1 + # and the older Ubuntu image, the linker does not link with `libresolv.so`. + # This results in crashes in `getaddrinfo()` since Ubuntu-18 GLIBC is 2.31. + # + # This problem does not occur on Ubuntu 22 and newer because GLIBC versions 2.34 + # and above include `dn_expand` in `libc.so`, eliminating the dependency on + # `libresolv.so`. + # + # We can bypass this problem by linking with "resolv" manually until we bump + # our base Linux image to Ubuntu 22. + extra-build-flag: --cmake-extra=-DCMAKE_EXE_LINKER_FLAGS="-lresolv" steps: - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ env.CRT_CI_ROLE }} aws-region: ${{ env.AWS_DEFAULT_REGION }} - # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - - name: Build ${{ env.PACKAGE_NAME }} + - name: Build ${{ matrix.compiler.name }} run: | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh - ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=${{ matrix.compiler }} + ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=${{ matrix.compiler.name }} ${{ matrix.compiler.extra-build-flag }} linux-debug: runs-on: ubuntu-24.04 # latest @@ -215,7 +232,7 @@ jobs: strategy: fail-fast: false matrix: - eventloop: ["-DAWS_USE_APPLE_NETWORK_FRAMEWORK=ON", "-DAWS_USE_APPLE_NETWORK_FRAMEWORK=OFF"] + eventloop: ["kqueue", "dispatch_queue"] steps: - uses: aws-actions/configure-aws-credentials@v4 with: @@ -225,7 +242,7 @@ jobs: run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" chmod a+x builder - ./builder build -p ${{ env.PACKAGE_NAME }} --cmake-extra=${{ matrix.eventloop }} + ./builder build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DAWS_USE_APPLE_NETWORK_FRAMEWORK=${{ matrix.eventloop == 'dispatch_queue' ? 'ON' : 'OFF' }} macos-x64: runs-on: macos-14-large # latest @@ -245,7 +262,7 @@ jobs: strategy: fail-fast: false matrix: - eventloop: ["-DAWS_USE_APPLE_NETWORK_FRAMEWORK=ON", "-DAWS_USE_APPLE_NETWORK_FRAMEWORK=OFF"] + eventloop: ["kqueue", "dispatch_queue"] steps: - uses: aws-actions/configure-aws-credentials@v4 with: @@ -255,7 +272,7 @@ jobs: run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" chmod a+x builder - ./builder build -p ${{ env.PACKAGE_NAME }} --cmake-extra=${{ matrix.eventloop }} --config Debug + ./builder build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DAWS_USE_APPLE_NETWORK_FRAMEWORK=${{ matrix.eventloop == 'dispatch_queue' && 'ON' || 'OFF' }} --config Debug freebsd: runs-on: ubuntu-24.04 # latest diff --git a/CMakeLists.txt b/CMakeLists.txt index c4660cb80..e881772d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -211,11 +211,11 @@ if (BUILD_RELOCATABLE_BINARIES) endif() if (USE_VSOCK) - target_compile_definitions(${PROJECT_NAME} PUBLIC "-DUSE_VSOCK") + target_compile_definitions(${PROJECT_NAME} PUBLIC "-DUSE_VSOCK") endif() if (AWS_USE_APPLE_NETWORK_FRAMEWORK) - target_compile_definitions(${PROJECT_NAME} PUBLIC "-DAWS_USE_APPLE_NETWORK_FRAMEWORK") + target_compile_definitions(${PROJECT_NAME} PUBLIC "-DAWS_USE_APPLE_NETWORK_FRAMEWORK") endif() target_include_directories(${PROJECT_NAME} PUBLIC diff --git a/include/aws/io/event_loop.h b/include/aws/io/event_loop.h index ac3532424..ffaa0f722 100644 --- a/include/aws/io/event_loop.h +++ b/include/aws/io/event_loop.h @@ -56,7 +56,7 @@ struct aws_event_loop_vtable { * Linux | AWS_EVENT_LOOP_EPOLL * Windows | AWS_EVENT_LOOP_IOCP * BSD Variants| AWS_EVENT_LOOP_KQUEUE - * MacOS | AWS_EVENT_LOOP_KQUEUE + * macOS | AWS_EVENT_LOOP_KQUEUE * iOS | AWS_EVENT_LOOP_DISPATCH_QUEUE */ enum aws_event_loop_type { diff --git a/include/aws/io/socket.h b/include/aws/io/socket.h index c3a4d994b..b0c6ad909 100644 --- a/include/aws/io/socket.h +++ b/include/aws/io/socket.h @@ -99,7 +99,8 @@ typedef void(aws_socket_on_connection_result_fn)(struct aws_socket *socket, int * A user may want to call aws_socket_set_options() on the new socket if different options are desired. * * new_socket is not yet assigned to an event-loop. The user should call aws_socket_assign_to_event_loop() before - * performing IO operations. The user must call `aws_socket_release()` when they're done with the socket, to free it. + * performing IO operations. The user must call `aws_socket_clean_up()` and "aws_mem_release()" when they're done with + * the new_socket, to free it. * * When error_code is AWS_ERROR_SUCCESS, new_socket is the recently accepted connection. * If error_code is non-zero, an error occurred and you should aws_socket_close() the socket. @@ -186,10 +187,6 @@ AWS_IO_API void aws_socket_clean_up(struct aws_socket *socket); * In TCP, LOCAL and VSOCK this function will not block. If the return value is successful, then you must wait on the * `on_connection_result()` callback to be invoked before using the socket. * - * The function will failed with error if the endpoint is invalid, except for Apple Network Framework. In Apple network - * framework, as connect is an async api, we would not know if the local endpoint is valid until we have the connection - * state returned in callback. The error will returned in `on_connection_result` callback - * * If an event_loop is provided for UDP sockets, a notification will be sent on * on_connection_result in the event-loop's thread. Upon completion, the socket will already be assigned * an event loop. If NULL is passed for UDP, it will immediately return upon success, but you must call diff --git a/source/darwin/secure_transport_tls_channel_handler.c b/source/darwin/secure_transport_tls_channel_handler.c index a06d140ee..f58248623 100644 --- a/source/darwin/secure_transport_tls_channel_handler.c +++ b/source/darwin/secure_transport_tls_channel_handler.c @@ -1111,7 +1111,7 @@ static struct aws_tls_ctx *s_tls_ctx_new(struct aws_allocator *alloc, const stru } #endif } else if (aws_tls_options_buf_is_set(&options->pkcs12)) { - AWS_LOGF_DEBUG(AWS_LS_IO_TLS, "static: a pkcs$12 certificate and key has been set, setting it up now."); + AWS_LOGF_DEBUG(AWS_LS_IO_TLS, "static: a pkcs#12 certificate and key has been set, setting it up now."); struct aws_byte_cursor pkcs12_blob_cur = aws_byte_cursor_from_buf(&options->pkcs12); struct aws_byte_cursor password_cur = aws_byte_cursor_from_buf(&options->pkcs12_password); diff --git a/source/event_loop.c b/source/event_loop.c index c5e0ea54c..d8b3ac879 100644 --- a/source/event_loop.c +++ b/source/event_loop.c @@ -104,10 +104,8 @@ enum aws_event_loop_type aws_event_loop_get_default_type(void) { #elif defined(AWS_OS_WINDOWS) return AWS_EVENT_LOOP_IOCP; #else - AWS_LOGF_ERROR( - AWS_LS_IO_EVENT_LOOP, - "Failed to get default event loop type. The library is not built correctly on the platform."); - return AWS_EVENT_LOOP_PLATFORM_DEFAULT; +# error \ + "Default event loop type required. Failed to get default event loop type. The library is not built correctly on the platform. " #endif } @@ -599,10 +597,9 @@ int aws_event_loop_connect_handle_to_io_completion_port( struct aws_event_loop *event_loop, struct aws_io_handle *handle) { - if (event_loop->vtable && event_loop->vtable->connect_to_io_completion_port) { - return event_loop->vtable->connect_to_io_completion_port(event_loop, handle); - } - + AWS_ASSERT(event_loop->vtable && event_loop->vtable->cancel_task); + return event_loop->vtable->connect_to_io_completion_port(event_loop, handle); + return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION); } @@ -613,9 +610,8 @@ int aws_event_loop_subscribe_to_io_events( aws_event_loop_on_event_fn *on_event, void *user_data) { - if (event_loop->vtable && event_loop->vtable->subscribe_to_io_events) { - return event_loop->vtable->subscribe_to_io_events(event_loop, handle, events, on_event, user_data); - } + AWS_ASSERT(event_loop && event_loop->vtable->free_io_event_resources); + return event_loop->vtable->subscribe_to_io_events(event_loop, handle, events, on_event, user_data); return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1e0c1cedb..0619703de 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,11 +54,15 @@ add_test_case(event_loop_multiple_stops) add_test_case(event_loop_group_setup_and_shutdown) add_test_case(event_loop_group_setup_and_shutdown_async) add_test_case(numa_aware_event_loop_group_setup_and_shutdown) -add_test_case(event_loop_all_types_creation) +add_test_case(event_loop_epoll_creation) +add_test_case(event_loop_iocp_creation) +add_test_case(event_loop_kqueue_creation) +add_test_case(event_loop_dispatch_queue_creation) add_test_case(io_testing_channel) -add_test_case(test_socket_impl_types_creation) +add_test_case(socket_posix_creation) +add_test_case(socket_winsock_creation) add_test_case(local_socket_communication) add_net_test_case(tcp_socket_communication) add_net_test_case(udp_socket_communication) diff --git a/tests/event_loop_test.c b/tests/event_loop_test.c index 477547cad..3f9fc3323 100644 --- a/tests/event_loop_test.c +++ b/tests/event_loop_test.c @@ -1009,33 +1009,53 @@ static int s_test_event_loop_creation( return AWS_OP_SUCCESS; } -/* Verify default event loop type */ -static int s_test_event_loop_all_types_creation(struct aws_allocator *allocator, void *ctx) { +static bool s_eventloop_test_enable_kqueue = false; +static bool s_eventloop_test_enable_epoll = false; +static bool s_eventloop_test_enable_iocp = false; +static bool s_eventloop_test_enable_dispatch_queue = false; + +static int s_test_event_loop_epoll_creation(struct aws_allocator *allocator, void *ctx) { (void)ctx; - bool enable_kqueue = false; - bool enable_epoll = false; - bool enable_iocp = false; - bool enable_dispatch_queue = false; -#ifdef AWS_ENABLE_KQUEUE - enable_kqueue = true; -#endif + #ifdef AWS_ENABLE_EPOLL - enable_epoll = true; + s_eventloop_test_enable_epoll = true; #endif + return s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_EPOLL, s_eventloop_test_enable_epoll); +} + +AWS_TEST_CASE(event_loop_epoll_creation, s_test_event_loop_epoll_creation) + +static int s_test_event_loop_iocp_creation(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + #ifdef AWS_ENABLE_IO_COMPLETION_PORTS - enable_iocp = true; + s_eventloop_test_enable_iocp = true; #endif -#ifdef AWS_ENABLE_DISPATCH_QUEUE - enable_dispatch_queue = true; + return s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_IOCP, s_eventloop_test_enable_iocp); +} + +AWS_TEST_CASE(event_loop_iocp_creation, s_test_event_loop_iocp_creation) + +static int s_test_event_loop_kqueue_creation(struct aws_allocator *allocator, void *ctx) { + (void)ctx; +#ifdef AWS_ENABLE_KQUEUE + s_eventloop_test_enable_kqueue = true; #endif + return s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_KQUEUE, s_eventloop_test_enable_kqueue); +} - return s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_EPOLL, enable_epoll) || - s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_IOCP, enable_iocp) || - s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_KQUEUE, enable_kqueue) || - s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_DISPATCH_QUEUE, enable_dispatch_queue); +AWS_TEST_CASE(event_loop_kqueue_creation, s_test_event_loop_kqueue_creation) + +static int s_test_event_loop_dispatch_queue_creation(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + +#ifdef AWS_ENABLE_DISPATCH_QUEUE + s_eventloop_test_enable_dispatch_queue = true; +#endif + return s_test_event_loop_creation(allocator, AWS_EVENT_LOOP_DISPATCH_QUEUE, s_eventloop_test_enable_dispatch_queue); } -AWS_TEST_CASE(event_loop_all_types_creation, s_test_event_loop_all_types_creation) +AWS_TEST_CASE(event_loop_dispatch_queue_creation, s_test_event_loop_dispatch_queue_creation) static int s_event_loop_test_stop_then_restart(struct aws_allocator *allocator, void *ctx) { (void)ctx; diff --git a/tests/socket_test.c b/tests/socket_test.c index f96b20e4f..f26db12e3 100644 --- a/tests/socket_test.c +++ b/tests/socket_test.c @@ -412,23 +412,31 @@ static int s_test_socket_creation(struct aws_allocator *alloc, enum aws_socket_i return AWS_OP_SUCCESS; } -static int s_test_socket_impl_types_creation(struct aws_allocator *allocator, void *ctx) { + +static int s_socket_test_posix_expected_result = AWS_ERROR_PLATFORM_NOT_SUPPORTED; +static int s_socket_test_winsock_expected_result = AWS_ERROR_PLATFORM_NOT_SUPPORTED; + +static int s_test_socket_posix_creation(struct aws_allocator *allocator, void *ctx) { (void)ctx; - int posix_expected_result = AWS_ERROR_PLATFORM_NOT_SUPPORTED; - int winsock_expected_result = AWS_ERROR_PLATFORM_NOT_SUPPORTED; + #if defined(AWS_ENABLE_KQUEUE) || defined(AWS_ENABLE_EPOLL) - posix_expected_result = AWS_OP_SUCCESS; + s_socket_test_posix_expected_result = AWS_OP_SUCCESS; #endif + return s_test_socket_creation(allocator, AWS_SOCKET_IMPL_POSIX, s_socket_test_posix_expected_result); +} + +AWS_TEST_CASE(socket_posix_creation, s_test_socket_posix_creation) + +static int s_test_socket_winsock_creation(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + #ifdef AWS_ENABLE_IO_COMPLETION_PORTS - winsock_expected_result = AWS_OP_SUCCESS; + s_socket_test_winsock_expected_result = AWS_OP_SUCCESS; #endif - // TODO: Apple Network Framework is not implemented yet. Add the related socket test later. - - return s_test_socket_creation(allocator, AWS_SOCKET_IMPL_POSIX, posix_expected_result) || - s_test_socket_creation(allocator, AWS_SOCKET_IMPL_WINSOCK, winsock_expected_result); + return s_test_socket_creation(allocator, AWS_SOCKET_IMPL_WINSOCK, s_socket_test_winsock_expected_result); } -AWS_TEST_CASE(test_socket_impl_types_creation, s_test_socket_impl_types_creation) +AWS_TEST_CASE(socket_winsock_creation, s_test_socket_winsock_creation) static int s_test_socket( struct aws_allocator *allocator,