Skip to content

Commit

Permalink
ARROW-12248: [C++] Avoid looking up ARROW_DEFAULT_MEMORY_POOL environ…
Browse files Browse the repository at this point in the history
…ment variable too late

In some situations (e.g. R bindings), default_memory_pool() may be called before the Arrow library's global variables were fully initialized.

Closes #9930 from pitrou/ARROW-12248-memory-pool-env-lookup

Authored-by: Antoine Pitrou <antoine@python.org>
Signed-off-by: David Li <li.davidm96@gmail.com>
  • Loading branch information
pitrou authored and lidavidm committed Apr 13, 2021
1 parent 57d430e commit a49d6e2
Showing 1 changed file with 41 additions and 33 deletions.
74 changes: 41 additions & 33 deletions cpp/src/arrow/memory_pool.cc
Expand Up @@ -105,8 +105,14 @@ struct SupportedBackend {
MemoryPoolBackend backend;
};

std::vector<SupportedBackend> SupportedBackends() {
std::vector<SupportedBackend> backends = {
// See ARROW-12248 for why we use static in-function singletons rather than
// global constants below (in SupportedBackends() and UserSelectedBackend()).
// In some contexts (especially R bindings) `default_memory_pool()` may be
// called before all globals are initialized, and then the ARROW_DEFAULT_MEMORY_POOL
// environment variable would be ignored.

const std::vector<SupportedBackend>& SupportedBackends() {
static std::vector<SupportedBackend> backends = {
#ifdef ARROW_JEMALLOC
{"jemalloc", MemoryPoolBackend::Jemalloc},
#endif
Expand All @@ -117,42 +123,44 @@ std::vector<SupportedBackend> SupportedBackends() {
return backends;
}

const std::vector<SupportedBackend> supported_backends = SupportedBackends();

// Return the MemoryPoolBackend selected by the user through the
// ARROW_DEFAULT_MEMORY_POOL environment variable, if any.
util::optional<MemoryPoolBackend> UserSelectedBackend() {
auto unsupported_backend = [](const std::string& name) {
std::vector<std::string> supported;
for (const auto backend : supported_backends) {
supported.push_back(std::string("'") + backend.name + "'");
static auto user_selected_backend = []() -> util::optional<MemoryPoolBackend> {
auto unsupported_backend = [](const std::string& name) {
std::vector<std::string> supported;
for (const auto backend : SupportedBackends()) {
supported.push_back(std::string("'") + backend.name + "'");
}
ARROW_LOG(WARNING) << "Unsupported backend '" << name << "' specified in "
<< kDefaultBackendEnvVar << " (supported backends are "
<< internal::JoinStrings(supported, ", ") << ")";
};

auto maybe_name = internal::GetEnvVar(kDefaultBackendEnvVar);
if (!maybe_name.ok()) {
return {};
}
ARROW_LOG(WARNING) << "Unsupported backend '" << name << "' specified in "
<< kDefaultBackendEnvVar << " (supported backends are "
<< internal::JoinStrings(supported, ", ") << ")";
};

auto maybe_name = internal::GetEnvVar(kDefaultBackendEnvVar);
if (!maybe_name.ok()) {
return {};
}
const auto name = *std::move(maybe_name);
if (name.empty()) {
// An empty environment variable is considered missing
const auto name = *std::move(maybe_name);
if (name.empty()) {
// An empty environment variable is considered missing
return {};
}
const auto found = std::find_if(
SupportedBackends().begin(), SupportedBackends().end(),
[&](const SupportedBackend& backend) { return name == backend.name; });
if (found != SupportedBackends().end()) {
return found->backend;
}
unsupported_backend(name);
return {};
}
const auto found =
std::find_if(supported_backends.begin(), supported_backends.end(),
[&](const SupportedBackend& backend) { return name == backend.name; });
if (found != supported_backends.end()) {
return found->backend;
}
unsupported_backend(name);
return {};
}
}();

const util::optional<MemoryPoolBackend> user_selected_backend = UserSelectedBackend();
return user_selected_backend;
}

MemoryPoolBackend DefaultBackend() {
auto backend = user_selected_backend;
auto backend = UserSelectedBackend();
if (backend.has_value()) {
return backend.value();
}
Expand Down Expand Up @@ -634,7 +642,7 @@ std::string ProxyMemoryPool::backend_name() const { return impl_->backend_name()

std::vector<std::string> SupportedMemoryBackendNames() {
std::vector<std::string> supported;
for (const auto backend : supported_backends) {
for (const auto backend : SupportedBackends()) {
supported.push_back(backend.name);
}
return supported;
Expand Down

0 comments on commit a49d6e2

Please sign in to comment.