Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package aws-c-event-stream for openSUSE:Factory checked in at 2025-07-15 16:43:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-c-event-stream (Old) and /work/SRC/openSUSE:Factory/.aws-c-event-stream.new.7373 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-c-event-stream" Tue Jul 15 16:43:44 2025 rev:7 rq:1293094 version:0.5.5 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-c-event-stream/aws-c-event-stream.changes 2025-03-13 15:07:14.660834700 +0100 +++ /work/SRC/openSUSE:Factory/.aws-c-event-stream.new.7373/aws-c-event-stream.changes 2025-07-15 16:44:44.037891756 +0200 @@ -1,0 +2,9 @@ +Fri Jul 11 10:50:04 UTC 2025 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to version 0.5.5 + * Make exports consistent by @DmitriyMusatkin in (#126) + * Fix path for diagram in README by @sfod in (#127) + * Remove Windows 2019 and add Windows 2025 with MSVC-17 by @TingDaoK in (#129) + * Continuation termination callback support by @bretambrose in (#128) + +------------------------------------------------------------------- Old: ---- v0.5.4.tar.gz New: ---- v0.5.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-c-event-stream.spec ++++++ --- /var/tmp/diff_new_pack.zPFgLh/_old 2025-07-15 16:44:44.761917930 +0200 +++ /var/tmp/diff_new_pack.zPFgLh/_new 2025-07-15 16:44:44.765918074 +0200 @@ -21,7 +21,7 @@ %define library_version 1.0.0 %define library_soversion 1 Name: aws-c-event-stream -Version: 0.5.4 +Version: 0.5.5 Release: 0 Summary: C99 implementation of the vnd.amazon.eventstream content-type License: Apache-2.0 ++++++ v0.5.4.tar.gz -> v0.5.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-event-stream-0.5.4/.github/workflows/ci.yml new/aws-c-event-stream-0.5.5/.github/workflows/ci.yml --- old/aws-c-event-stream-0.5.4/.github/workflows/ci.yml 2025-03-06 20:23:11.000000000 +0100 +++ new/aws-c-event-stream-0.5.5/.github/workflows/ci.yml 2025-06-20 23:14:43.000000000 +0200 @@ -105,7 +105,7 @@ ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DBUILD_SHARED_LIBS=ON windows: - runs-on: windows-2022 # latest + runs-on: windows-2025 # latest steps: - uses: aws-actions/configure-aws-credentials@v4 with: @@ -116,8 +116,8 @@ python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" python builder.pyz build -p ${{ env.PACKAGE_NAME }} - windows-vc14: - runs-on: windows-2019 # windows-2019 is last env with Visual Studio 2015 (v14.0) + windows-vc17: + runs-on: windows-2025 # latest strategy: matrix: arch: [x86, x64] @@ -129,10 +129,10 @@ - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" - python builder.pyz build -p ${{ env.PACKAGE_NAME }} --target windows-${{ matrix.arch }} --compiler msvc-14 + python builder.pyz build -p ${{ env.PACKAGE_NAME }} --target windows-${{ matrix.arch }} --compiler msvc-17 windows-shared-libs: - runs-on: windows-2022 # latest + runs-on: windows-2025 # latest steps: - uses: aws-actions/configure-aws-credentials@v4 with: @@ -144,7 +144,7 @@ python builder.pyz build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DBUILD_SHARED_LIBS=ON windows-app-verifier: - runs-on: windows-2022 # latest + runs-on: windows-2025 # latest steps: - uses: aws-actions/configure-aws-credentials@v4 with: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-event-stream-0.5.4/README.md new/aws-c-event-stream-0.5.5/README.md --- old/aws-c-event-stream-0.5.4/README.md 2025-03-06 20:23:11.000000000 +0100 +++ new/aws-c-event-stream-0.5.5/README.md 2025-06-20 23:14:43.000000000 +0200 @@ -70,4 +70,4 @@ The following diagram shows the components that make up a message and a header. There are multiple headers per message. - + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-event-stream-0.5.4/include/aws/event-stream/event_stream_exports.h new/aws-c-event-stream-0.5.5/include/aws/event-stream/event_stream_exports.h --- old/aws-c-event-stream-0.5.4/include/aws/event-stream/event_stream_exports.h 2025-03-06 20:23:11.000000000 +0100 +++ new/aws-c-event-stream-0.5.5/include/aws/event-stream/event_stream_exports.h 2025-06-20 23:14:43.000000000 +0200 @@ -4,7 +4,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ -#if defined(USE_WINDOWS_DLL_SEMANTICS) || defined(WIN32) +#if defined(AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined(_WIN32) # ifdef AWS_EVENT_STREAM_USE_IMPORT_EXPORT # ifdef AWS_EVENT_STREAM_EXPORTS # define AWS_EVENT_STREAM_API __declspec(dllexport) @@ -15,15 +15,14 @@ # define AWS_EVENT_STREAM_API # endif /* AWS_EVENT_STREAM_USE_IMPORT_EXPORT */ -#else /* defined (USE_WINDOWS_DLL_SEMANTICS) || defined (WIN32) */ +#else /* defined (AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) */ -# if ((__GNUC__ >= 4) || defined(__clang__)) && defined(AWS_EVENT_STREAM_USE_IMPORT_EXPORT) && \ - defined(AWS_EVENT_STREAM_EXPORTS) +# if defined(AWS_EVENT_STREAM_USE_IMPORT_EXPORT) && defined(AWS_EVENT_STREAM_EXPORTS) # define AWS_EVENT_STREAM_API __attribute__((visibility("default"))) # else # define AWS_EVENT_STREAM_API -# endif /* __GNUC__ >= 4 || defined(__clang__) */ +# endif -#endif /* defined (USE_WINDOWS_DLL_SEMANTICS) || defined (WIN32) */ +#endif /* defined (AWS_CRT_USE_WINDOWS_DLL_SEMANTICS) || defined (_WIN32) */ #endif /* AWS_EVENT_STREAM_EXPORTS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-event-stream-0.5.4/include/aws/event-stream/event_stream_rpc_client.h new/aws-c-event-stream-0.5.5/include/aws/event-stream/event_stream_rpc_client.h --- old/aws-c-event-stream-0.5.4/include/aws/event-stream/event_stream_rpc_client.h 2025-03-06 20:23:11.000000000 +0100 +++ new/aws-c-event-stream-0.5.5/include/aws/event-stream/event_stream_rpc_client.h 2025-06-20 23:14:43.000000000 +0200 @@ -10,6 +10,7 @@ AWS_PUSH_SANE_WARNING_LEVEL struct aws_channel; +struct aws_event_loop; struct aws_event_stream_rpc_client_connection; struct aws_event_stream_rpc_client_continuation_token; @@ -30,9 +31,15 @@ struct aws_event_stream_rpc_client_continuation_token *token, void *user_data); +/** + * Invoked after a continuation has been fully destroyed. Listeners know that no further callbacks are possible. + */ +typedef void(aws_event_stream_rpc_client_stream_continuation_terminated_fn)(void *user_data); + struct aws_event_stream_rpc_client_stream_continuation_options { aws_event_stream_rpc_client_stream_continuation_fn *on_continuation; aws_event_stream_rpc_client_stream_continuation_closed_fn *on_continuation_closed; + aws_event_stream_rpc_client_stream_continuation_terminated_fn *on_continuation_terminated; void *user_data; }; @@ -74,6 +81,11 @@ void *user_data); /** + * Invoked when a connection has been completely destroyed. + */ +typedef void(aws_event_stream_rpc_client_on_connection_terminated_fn)(void *user_data); + +/** * Invoked whenever a message has been flushed to the channel. */ typedef void(aws_event_stream_rpc_client_message_flush_fn)(int error_code, void *user_data); @@ -93,6 +105,7 @@ aws_event_stream_rpc_client_on_connection_setup_fn *on_connection_setup; aws_event_stream_rpc_client_connection_protocol_message_fn *on_connection_protocol_message; aws_event_stream_rpc_client_on_connection_shutdown_fn *on_connection_shutdown; + aws_event_stream_rpc_client_on_connection_terminated_fn *on_connection_terminated; void *user_data; }; @@ -143,6 +156,12 @@ void *user_data); /** + * Returns the event loop that a connection is seated on. + */ +AWS_EVENT_STREAM_API struct aws_event_loop *aws_event_stream_rpc_client_connection_get_event_loop( + const struct aws_event_stream_rpc_client_connection *connection); + +/** * Create a new stream. continuation_option's callbacks will not be invoked, and nothing will be sent across the wire * until aws_event_stream_rpc_client_continuation_activate() is invoked. * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-event-stream-0.5.4/source/event_stream_rpc_client.c new/aws-c-event-stream-0.5.5/source/event_stream_rpc_client.c --- old/aws-c-event-stream-0.5.4/source/event_stream_rpc_client.c 2025-03-06 20:23:11.000000000 +0100 +++ new/aws-c-event-stream-0.5.5/source/event_stream_rpc_client.c 2025-06-20 23:14:43.000000000 +0200 @@ -14,6 +14,8 @@ #include <inttypes.h> +#include "aws/io/event_loop.h" + #ifdef _MSC_VER /* allow declared initializer using address of automatic variable */ # pragma warning(disable : 4221) @@ -28,6 +30,7 @@ struct aws_allocator *allocator; struct aws_hash_table continuation_table; struct aws_client_bootstrap *bootstrap_ref; + struct aws_event_loop *event_loop; struct aws_atomic_var ref_count; struct aws_channel *channel; struct aws_channel_handler *event_stream_handler; @@ -39,6 +42,7 @@ aws_event_stream_rpc_client_on_connection_setup_fn *on_connection_setup; aws_event_stream_rpc_client_connection_protocol_message_fn *on_connection_protocol_message; aws_event_stream_rpc_client_on_connection_shutdown_fn *on_connection_shutdown; + aws_event_stream_rpc_client_on_connection_terminated_fn *on_connection_terminated; void *user_data; bool bootstrap_owned; bool enable_read_back_pressure; @@ -49,6 +53,7 @@ struct aws_event_stream_rpc_client_connection *connection; aws_event_stream_rpc_client_stream_continuation_fn *continuation_fn; aws_event_stream_rpc_client_stream_continuation_closed_fn *closed_fn; + aws_event_stream_rpc_client_stream_continuation_terminated_fn *terminated_fn; void *user_data; struct aws_atomic_var ref_count; struct aws_atomic_var is_closed; @@ -187,9 +192,7 @@ aws_event_stream_rpc_client_connection_release(connection); } -/* Set each continuation's is_closed=true. - * A lock MUST be held while calling this. - * For use with aws_hash_table_foreach(). */ +/* Set each continuation's is_closed=true. */ static int s_mark_each_continuation_closed(void *context, struct aws_hash_element *p_element) { (void)context; struct aws_event_stream_rpc_client_continuation_token *continuation = p_element->value; @@ -233,18 +236,31 @@ static void s_clear_continuation_table(struct aws_event_stream_rpc_client_connection *connection) { AWS_ASSERT(!aws_event_stream_rpc_client_connection_is_open(connection)); + struct aws_hash_table temp_table; + aws_hash_table_init( + &temp_table, + connection->allocator, + 64, + aws_event_stream_rpc_hash_streamid, + aws_event_stream_rpc_streamid_eq, + NULL, + NULL); + /* Use lock to ensure synchronization with code that adds entries to table. * Since connection was just marked closed, no further entries will be - * added to table once we acquire the lock. */ + * added to table once we acquire the lock. + * + * While no further entries can be added, there are concurrent execution paths where things can be + * removed. So rather than iterating the connection's table, swap it out for an empty one and iterate + * the temporary table instead. Removing from an empty table will be harmless. + */ aws_mutex_lock(&connection->stream_lock); - aws_hash_table_foreach(&connection->continuation_table, s_mark_each_continuation_closed, NULL); + aws_hash_table_swap(&temp_table, &connection->continuation_table); aws_mutex_unlock(&connection->stream_lock); - /* Now release lock before invoking callbacks. - * It's safe to alter the table now without a lock, since no further - * entries can be added, and we've gone through the critical section - * above to ensure synchronization */ - aws_hash_table_foreach(&connection->continuation_table, s_complete_and_clear_each_continuation, NULL); + aws_hash_table_foreach(&temp_table, s_mark_each_continuation_closed, NULL); + aws_hash_table_foreach(&temp_table, s_complete_and_clear_each_continuation, NULL); + aws_hash_table_clean_up(&temp_table); } int aws_event_stream_rpc_client_connection_connect( @@ -268,6 +284,8 @@ connection->allocator = allocator; aws_atomic_init_int(&connection->ref_count, 1); connection->bootstrap_ref = conn_options->bootstrap; + connection->event_loop = aws_event_loop_group_get_next_loop(connection->bootstrap_ref->event_loop_group); + /* this is released in the connection release which gets called regardless of if this function is successful or * not*/ aws_client_bootstrap_acquire(connection->bootstrap_ref); @@ -276,6 +294,7 @@ aws_mutex_init(&connection->stream_lock); connection->on_connection_shutdown = conn_options->on_connection_shutdown; + connection->on_connection_terminated = conn_options->on_connection_terminated; connection->on_connection_protocol_message = conn_options->on_connection_protocol_message; connection->on_connection_setup = conn_options->on_connection_setup; connection->user_data = conn_options->user_data; @@ -307,6 +326,7 @@ .enable_read_back_pressure = false, .setup_callback = s_on_channel_setup_fn, .shutdown_callback = s_on_channel_shutdown_fn, + .requested_event_loop = connection->event_loop, }; if (aws_client_bootstrap_new_socket_channel(&bootstrap_options)) { @@ -340,7 +360,15 @@ AWS_LOGF_DEBUG(AWS_LS_EVENT_STREAM_RPC_CLIENT, "id=%p: destroying connection.", (void *)connection); aws_hash_table_clean_up(&connection->continuation_table); aws_client_bootstrap_release(connection->bootstrap_ref); + + aws_event_stream_rpc_client_on_connection_terminated_fn *terminated_fn = connection->on_connection_terminated; + void *terminated_user_data = connection->user_data; + aws_mem_release(connection->allocator, connection); + + if (terminated_fn) { + terminated_fn(terminated_user_data); + } } void aws_event_stream_rpc_client_connection_release(const struct aws_event_stream_rpc_client_connection *connection) { @@ -434,13 +462,19 @@ AWS_FATAL_ASSERT(message_args->continuation && "end stream flag was set but it wasn't on a continuation"); aws_atomic_store_int(&message_args->continuation->is_closed, 1U); + int was_present = 0; aws_mutex_lock(&message_args->connection->stream_lock); aws_hash_table_remove( - &message_args->connection->continuation_table, &message_args->continuation->stream_id, NULL, NULL); + &message_args->connection->continuation_table, &message_args->continuation->stream_id, NULL, &was_present); aws_mutex_unlock(&message_args->connection->stream_lock); - /* Lock must NOT be held while invoking callback */ - s_complete_continuation(message_args->continuation); + /* + * Whoever successfully removes the continuation from the table gets to complete it. + * Lock must NOT be held while invoking callback + */ + if (was_present) { + s_complete_continuation(message_args->continuation); + } } message_args->flush_fn(error_code, message_args->user_data); @@ -770,7 +804,6 @@ aws_mutex_unlock(&connection->stream_lock); continuation->continuation_fn(continuation, &message_args, continuation->user_data); - aws_event_stream_rpc_client_continuation_release(continuation); /* if it was a terminal stream message purge it from the hash table. The delete will decref the continuation. */ if (message_flags & AWS_EVENT_STREAM_RPC_MESSAGE_FLAG_TERMINATE_STREAM) { @@ -780,13 +813,21 @@ (void *)connection, (void *)continuation); aws_atomic_store_int(&continuation->is_closed, 1U); + int was_present = 0; aws_mutex_lock(&connection->stream_lock); - aws_hash_table_remove(&connection->continuation_table, &stream_id, NULL, NULL); + aws_hash_table_remove(&connection->continuation_table, &stream_id, NULL, &was_present); aws_mutex_unlock(&connection->stream_lock); - /* Note that we do not invoke callback while holding lock */ - s_complete_continuation(continuation); + /* + * Whoever successfully removes the continuation from the table gets to complete it. + * Lock must NOT be held while invoking callback + */ + if (was_present) { + s_complete_continuation(continuation); + } } + + aws_event_stream_rpc_client_continuation_release(continuation); } else { if (message_type <= AWS_EVENT_STREAM_RPC_MESSAGE_TYPE_APPLICATION_ERROR || message_type >= AWS_EVENT_STREAM_RPC_MESSAGE_TYPE_COUNT) { @@ -915,6 +956,7 @@ aws_atomic_init_int(&continuation->is_complete, 0); continuation->continuation_fn = continuation_options->on_continuation; continuation->closed_fn = continuation_options->on_continuation_closed; + continuation->terminated_fn = continuation_options->on_continuation_terminated; continuation->user_data = continuation_options->user_data; return continuation; @@ -959,7 +1001,15 @@ if (ref_count == 1) { struct aws_allocator *allocator = continuation_mut->connection->allocator; aws_event_stream_rpc_client_connection_release(continuation_mut->connection); + + aws_event_stream_rpc_client_stream_continuation_terminated_fn *terminated_fn = continuation_mut->terminated_fn; + void *terminated_user_data = continuation_mut->user_data; + aws_mem_release(allocator, continuation_mut); + + if (terminated_fn) { + terminated_fn(terminated_user_data); + } } } @@ -1062,3 +1112,13 @@ return s_send_protocol_message( continuation->connection, continuation, NULL, message_args, continuation->stream_id, flush_fn, user_data); } + +struct aws_event_loop *aws_event_stream_rpc_client_connection_get_event_loop( + const struct aws_event_stream_rpc_client_connection *connection) { + + if (!connection) { + return NULL; + } + + return connection->event_loop; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-event-stream-0.5.4/source/event_stream_rpc_server.c new/aws-c-event-stream-0.5.5/source/event_stream_rpc_server.c --- old/aws-c-event-stream-0.5.4/source/event_stream_rpc_server.c 2025-03-06 20:23:11.000000000 +0100 +++ new/aws-c-event-stream-0.5.5/source/event_stream_rpc_server.c 2025-06-20 23:14:43.000000000 +0200 @@ -901,13 +901,26 @@ struct aws_hash_element *continuation_element = NULL; if (aws_hash_table_find(&connection->continuation_table, &stream_id, &continuation_element) || !continuation_element) { - AWS_LOGF_ERROR( - AWS_LS_EVENT_STREAM_RPC_SERVER, - "id=%p: stream_id does not have a corresponding continuation", - (void *)connection); - aws_raise_error(AWS_ERROR_EVENT_STREAM_RPC_PROTOCOL_ERROR); - s_send_connection_level_error( - connection, AWS_EVENT_STREAM_RPC_MESSAGE_TYPE_PROTOCOL_ERROR, 0, &s_invalid_client_stream_id_error); + if ((message_flags & AWS_EVENT_STREAM_RPC_MESSAGE_FLAG_TERMINATE_STREAM) == 0) { + AWS_LOGF_ERROR( + AWS_LS_EVENT_STREAM_RPC_SERVER, + "id=%p: stream_id does not have a corresponding continuation", + (void *)connection); + aws_raise_error(AWS_ERROR_EVENT_STREAM_RPC_PROTOCOL_ERROR); + s_send_connection_level_error( + connection, + AWS_EVENT_STREAM_RPC_MESSAGE_TYPE_PROTOCOL_ERROR, + 0, + &s_invalid_client_stream_id_error); + } else { + /* Simultaneous close can trip this condition */ + AWS_LOGF_DEBUG( + AWS_LS_EVENT_STREAM_RPC_SERVER, + "id=%p: received a terminate stream message for stream_id %d, which no longer has a " + "corresponding continuation", + (void *)connection, + (int)stream_id); + } return; }