Skip to content

Commit

Permalink
Merge branch 'runtime_select_event_loop' of github.com:awslabs/aws-c-…
Browse files Browse the repository at this point in the history
…io into grand_dispatch_queue
  • Loading branch information
xiazhvera committed Jan 7, 2025
2 parents a93216b + 5e1e728 commit 893f94b
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 72 deletions.
61 changes: 39 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion include/aws/io/event_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 2 additions & 5 deletions include/aws/io/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion source/darwin/secure_transport_tls_channel_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
18 changes: 7 additions & 11 deletions source/event_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down
8 changes: 6 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
56 changes: 38 additions & 18 deletions tests/event_loop_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 18 additions & 10 deletions tests/socket_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 893f94b

Please sign in to comment.