Skip to content

Commit ebb8815

Browse files
laramielcopybara-github
authored andcommitted
Ensure aws library initialization is called by GetAwsAllocator()
Also rework aws global variables into a singleton AwsApi class, and update the lazy initialization of the class members. PiperOrigin-RevId: 749910414 Change-Id: Ia3a0f5cd658cc1a69a59b5a034a0918b6abd4437
1 parent a40c3e2 commit ebb8815

File tree

5 files changed

+98
-59
lines changed

5 files changed

+98
-59
lines changed

tensorstore/internal/aws/BUILD

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ tensorstore_cc_library(
2020
"@aws_c_common",
2121
"@aws_c_http",
2222
"@aws_c_io",
23-
"@com_google_absl//absl/base",
2423
"@com_google_absl//absl/base:core_headers",
2524
"@com_google_absl//absl/base:log_severity",
25+
"@com_google_absl//absl/base:no_destructor",
2626
"@com_google_absl//absl/debugging:leak_check",
2727
"@com_google_absl//absl/log:absl_log",
28+
"@com_google_absl//absl/synchronization",
2829
],
2930
)
3031

tensorstore/internal/aws/aws_api.cc

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
#include <string_view>
2424

2525
#include "absl/base/attributes.h"
26-
#include "absl/base/call_once.h"
2726
#include "absl/base/log_severity.h"
27+
#include "absl/base/no_destructor.h"
28+
#include "absl/base/thread_annotations.h"
2829
#include "absl/debugging/leak_check.h"
2930
#include "absl/log/absl_log.h"
31+
#include "absl/synchronization/mutex.h"
3032
#include <aws/auth/auth.h>
3133
#include <aws/cal/cal.h>
3234
#include <aws/common/allocator.h>
@@ -145,74 +147,104 @@ aws_logger s_absl_logger{
145147
};
146148

147149
// AWS apis rely on global initialization; do that here.
148-
ABSL_CONST_INIT absl::once_flag g_init;
149-
150-
aws_event_loop_group *g_event_loop_group = nullptr;
151-
aws_host_resolver *g_resolver = nullptr;
152-
aws_client_bootstrap *g_client_bootstrap = nullptr;
153-
aws_tls_ctx *g_tls_ctx = nullptr;
154-
155-
void InitAwsLibraries() {
156-
absl::LeakCheckDisabler disabler;
157-
158-
auto *allocator = GetAwsAllocator();
159-
160-
/* Initialize AWS libraries.*/
161-
aws_common_library_init(allocator);
162-
163-
s_absl_logger.allocator = allocator;
164-
aws_logger_set(&s_absl_logger);
165-
166-
aws_cal_library_init(allocator);
167-
aws_io_library_init(allocator);
168-
aws_http_library_init(allocator);
169-
aws_auth_library_init(allocator);
170-
171-
/* event loop */
172-
g_event_loop_group = aws_event_loop_group_new_default(allocator, 0, nullptr);
173-
174-
/* resolver */
175-
aws_host_resolver_default_options resolver_options;
176-
AWS_ZERO_STRUCT(resolver_options);
177-
resolver_options.el_group = g_event_loop_group;
178-
resolver_options.max_entries = 32; // defaults to 8?
179-
g_resolver = aws_host_resolver_new_default(allocator, &resolver_options);
180-
181-
/* client bootstrap */
182-
aws_client_bootstrap_options bootstrap_options;
183-
AWS_ZERO_STRUCT(bootstrap_options);
184-
bootstrap_options.event_loop_group = g_event_loop_group;
185-
bootstrap_options.host_resolver = g_resolver;
186-
g_client_bootstrap = aws_client_bootstrap_new(allocator, &bootstrap_options);
187-
if (g_client_bootstrap == nullptr) {
188-
ABSL_LOG(FATAL) << "ERROR initializing client bootstrap: "
189-
<< aws_error_debug_str(aws_last_error());
150+
class AwsApi {
151+
public:
152+
AwsApi() : allocator_(aws_default_allocator()) {
153+
absl::LeakCheckDisabler disabler;
154+
155+
/* Initialize AWS libraries.*/
156+
aws_common_library_init(allocator_);
157+
158+
s_absl_logger.allocator = allocator_;
159+
aws_logger_set(&s_absl_logger);
160+
161+
aws_cal_library_init(allocator_);
162+
aws_io_library_init(allocator_);
163+
aws_http_library_init(allocator_);
164+
aws_auth_library_init(allocator_);
165+
}
166+
167+
aws_allocator *allocator() { return allocator_; }
168+
169+
aws_client_bootstrap *client_bootstrap() ABSL_LOCKS_EXCLUDED(mutex_) {
170+
absl::MutexLock l(&mutex_);
171+
init_client_bootstrap();
172+
return client_bootstrap_;
173+
}
174+
175+
aws_tls_ctx *tls_ctx() ABSL_LOCKS_EXCLUDED(mutex_) {
176+
absl::MutexLock l(&mutex_);
177+
init_tls_ctx();
178+
return tls_ctx_;
179+
}
180+
181+
private:
182+
void init_event_loop_group() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
183+
if (event_loop_group_ != nullptr) return;
184+
event_loop_group_ =
185+
aws_event_loop_group_new_default(allocator_, 0, nullptr);
190186
}
191187

192-
AwsTlsCtx tls_ctx = AwsTlsCtxBuilder(allocator).Build();
193-
if (tls_ctx == nullptr) {
194-
ABSL_LOG(FATAL) << "ERROR initializing TLS context: "
195-
<< aws_error_debug_str(aws_last_error());
188+
void init_resolver() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
189+
if (resolver_ != nullptr) return;
190+
init_event_loop_group();
191+
192+
aws_host_resolver_default_options resolver_options;
193+
AWS_ZERO_STRUCT(resolver_options);
194+
resolver_options.el_group = event_loop_group_;
195+
resolver_options.max_entries = 32; // defaults to 8?
196+
resolver_ = aws_host_resolver_new_default(allocator_, &resolver_options);
197+
}
198+
199+
void init_client_bootstrap() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
200+
if (client_bootstrap_ != nullptr) return;
201+
init_event_loop_group();
202+
init_resolver();
203+
204+
aws_client_bootstrap_options bootstrap_options;
205+
AWS_ZERO_STRUCT(bootstrap_options);
206+
bootstrap_options.event_loop_group = event_loop_group_;
207+
bootstrap_options.host_resolver = resolver_;
208+
client_bootstrap_ =
209+
aws_client_bootstrap_new(allocator_, &bootstrap_options);
210+
if (client_bootstrap_ == nullptr) {
211+
ABSL_LOG(FATAL) << "ERROR initializing client bootstrap: "
212+
<< aws_error_debug_str(aws_last_error());
213+
}
214+
}
215+
216+
void init_tls_ctx() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
217+
if (tls_ctx_ != nullptr) return;
218+
auto my_tls_ctx = AwsTlsCtxBuilder(allocator_).Build();
219+
if (my_tls_ctx == nullptr) {
220+
ABSL_LOG(FATAL) << "ERROR initializing TLS context: "
221+
<< aws_error_debug_str(aws_last_error());
222+
}
223+
tls_ctx_ = my_tls_ctx.release();
196224
}
197-
g_tls_ctx = tls_ctx.release();
225+
226+
absl::Mutex mutex_;
227+
aws_allocator *allocator_ = nullptr;
228+
aws_event_loop_group *event_loop_group_ ABSL_GUARDED_BY(mutex_) = nullptr;
229+
aws_host_resolver *resolver_ ABSL_GUARDED_BY(mutex_) = nullptr;
230+
aws_client_bootstrap *client_bootstrap_ ABSL_GUARDED_BY(mutex_) = nullptr;
231+
aws_tls_ctx *tls_ctx_ ABSL_GUARDED_BY(mutex_) = nullptr;
232+
};
233+
234+
AwsApi &GetAwsApi() {
235+
static absl::NoDestructor<AwsApi> aws_api;
236+
return *aws_api;
198237
}
199238

200239
} // namespace
201240

202-
aws_allocator *GetAwsAllocator() {
203-
// The default allocator is used for all AWS API objects.
204-
return aws_default_allocator();
205-
}
241+
aws_allocator *GetAwsAllocator() { return GetAwsApi().allocator(); }
206242

207243
aws_client_bootstrap *GetAwsClientBootstrap() {
208-
absl::call_once(g_init, InitAwsLibraries);
209-
return g_client_bootstrap;
244+
return GetAwsApi().client_bootstrap();
210245
}
211246

212-
aws_tls_ctx *GetAwsTlsCtx() {
213-
absl::call_once(g_init, InitAwsLibraries);
214-
return g_tls_ctx;
215-
}
247+
aws_tls_ctx *GetAwsTlsCtx() { return GetAwsApi().tls_ctx(); }
216248

217249
} // namespace internal_aws
218250
} // namespace tensorstore

tensorstore/kvstore/s3/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ tensorstore_cc_library(
3030
"//tensorstore/internal:intrusive_ptr",
3131
"//tensorstore/internal:source_location",
3232
"//tensorstore/internal:uri_utils",
33+
"//tensorstore/internal/aws:aws_api",
3334
"//tensorstore/internal/aws:aws_credentials",
3435
"//tensorstore/internal/cache_key",
3536
"//tensorstore/internal/digest:sha256",
@@ -380,6 +381,7 @@ tensorstore_cc_library(
380381
"//tensorstore:json_serialization_options_base",
381382
"//tensorstore/internal:type_traits",
382383
"//tensorstore/internal:uri_utils",
384+
"//tensorstore/internal/aws:aws_api",
383385
"//tensorstore/internal/aws:aws_credentials",
384386
"//tensorstore/internal/aws/credentials:common",
385387
"//tensorstore/internal/json_binding",

tensorstore/kvstore/s3/aws_credentials_spec.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "absl/strings/str_cat.h"
2727
#include <aws/common/error.h>
2828
#include <nlohmann/json_fwd.hpp>
29+
#include "tensorstore/internal/aws/aws_api.h"
2930
#include "tensorstore/internal/aws/aws_credentials.h"
3031
#include "tensorstore/internal/aws/credentials/common.h"
3132
#include "tensorstore/internal/json_binding/bindable.h"
@@ -166,6 +167,7 @@ Result<AwsCredentialsProvider> MakeAwsCredentialsProvider(const Spec& spec) {
166167
}
167168
};
168169

170+
(void)internal_aws::GetAwsAllocator(); // Force AWS library initialization.
169171
AwsCredentialsProvider credentials_provider =
170172
std::visit(MakeCredentialsVisitor{}, spec.config);
171173

tensorstore/kvstore/s3/s3_key_value_store.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "absl/time/clock.h"
3838
#include "absl/time/time.h"
3939
#include "tensorstore/context.h"
40+
#include "tensorstore/internal/aws/aws_api.h"
4041
#include "tensorstore/internal/aws/aws_credentials.h"
4142
#include "tensorstore/internal/data_copy_concurrency_resource.h"
4243
#include "tensorstore/internal/digest/sha256.h"
@@ -1342,6 +1343,7 @@ Future<const S3EndpointRegion> S3KeyValueStore::MaybeResolveRegion() {
13421343
}
13431344

13441345
Future<kvstore::DriverPtr> S3KeyValueStoreSpec::DoOpen() const {
1346+
(void)internal_aws::GetAwsAllocator(); // Force AWS library initialization.
13451347
// TODO: The transport should support the AWS_CA_BUNDLE environment
13461348
// variable.
13471349
TENSORSTORE_ASSIGN_OR_RETURN(

0 commit comments

Comments
 (0)