blob: 466b3f504598447571f0beaf7b4e227e77a70648 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/forensics/exceptions/handler/component_lookup.h"
#include <lib/syslog/cpp/macros.h>
#include "src/developer/forensics/utils/errors.h"
#include "src/developer/forensics/utils/fidl/oneshot_ptr.h"
#include "src/developer/forensics/utils/fit/promise.h"
#include "src/lib/fxl/macros.h"
namespace forensics {
namespace exceptions {
namespace handler {
namespace {
using fuchsia::sys::internal::CrashIntrospect_FindComponentByThreadKoid_Result;
using fuchsia::sys::internal::SourceIdentity;
// Wraps around fuchsia::sys::internal::CrashIntrospectPtr to handle establishing the connection,
// losing the connection, waiting for the callback, enforcing a timeout, etc.
//
// GetSourceIdentity() is expected to be called only once.
class ComponentLookup {
public:
// fuchsia.sys.internal.CrashIntrospect is expected to be in |services|.
ComponentLookup(async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services)
: introspect_(dispatcher, services) {}
::fit::promise<SourceIdentity> GetSourceIdentity(zx_koid_t process_koid, fit::Timeout timeout);
private:
fidl::OneShotPtr<fuchsia::sys::internal::CrashIntrospect, SourceIdentity> introspect_;
};
::fit::promise<SourceIdentity> ComponentLookup::GetSourceIdentity(zx_koid_t thread_koid,
fit::Timeout timeout) {
introspect_->FindComponentByThreadKoid(
thread_koid, [this](CrashIntrospect_FindComponentByThreadKoid_Result result) {
if (introspect_.IsAlreadyDone()) {
return;
}
if (result.is_response()) {
introspect_.CompleteOk(std::move(result.response().component_info));
} else {
// ZX_ERR_NOT_FOUND most likely means a thread from a process outside a component,
// which is not an error.
if (result.err() != ZX_ERR_NOT_FOUND) {
FX_PLOGS(WARNING, result.err()) << "Failed FindComponentByProcessKoid";
}
introspect_.CompleteError(Error::kDefault);
}
});
return introspect_.WaitForDone(std::move(timeout)).or_else([](const Error& error) {
return ::fit::error();
});
}
} // namespace
::fit::promise<SourceIdentity> GetComponentSourceIdentity(
async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
fit::Timeout timeout, zx_koid_t thread_koid) {
auto component_lookup = std::make_unique<ComponentLookup>(dispatcher, services);
// We must store the promise in a variable due to the fact that the order of evaluation of
// function parameters is undefined.
auto component = component_lookup->GetSourceIdentity(thread_koid, std::move(timeout));
return fit::ExtendArgsLifetimeBeyondPromise(/*promise=*/std::move(component),
/*args=*/std::move(component_lookup));
}
} // namespace handler
} // namespace exceptions
} // namespace forensics