## Problem When the new setting ``` set target.parallel-module-load true ``` was added, lldb began fetching modules from the devices from multiple threads simultaneously. This caused crashes of lldb when debugging on android devices. The top of the stack in the crash look something like this: ``` #0 0x0000555aaf2b27fe llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/llvm/bin/lldb-dap+0xb87fe) #1 0x0000555aaf2b0a99 llvm::sys::RunSignalHandlers() (/opt/llvm/bin/lldb-dap+0xb6a99) #2 0x0000555aaf2b2fda SignalHandler(int, siginfo_t*, void*) (/opt/llvm/bin/lldb-dap+0xb8fda) #3 0x00007f9c02444560 __restore_rt /home/engshare/third-party2/glibc/2.34/src/glibc-2.34/signal/../sysdeps/unix/sysv/linux/libc_sigaction.c:13:0 #4 0x00007f9c04ea7707 lldb_private::ConnectionFileDescriptor::Disconnect(lldb_private::Status*) (usr/bin/../lib/liblldb.so.15+0x22a7707) #5 0x00007f9c04ea5b41 lldb_private::ConnectionFileDescriptor::~ConnectionFileDescriptor() (usr/bin/../lib/liblldb.so.15+0x22a5b41) #6 0x00007f9c04ea5c1e lldb_private::ConnectionFileDescriptor::~ConnectionFileDescriptor() (usr/bin/../lib/liblldb.so.15+0x22a5c1e) #7 0x00007f9c052916ff lldb_private::platform_android::AdbClient::SyncService::Stat(lldb_private::FileSpec const&, unsigned int&, unsigned int&, unsigned int&) (usr/bin/../lib/liblldb.so.15+0x26916ff) #8 0x00007f9c0528b9dc lldb_private::platform_android::PlatformAndroid::GetFile(lldb_private::FileSpec const&, lldb_private::FileSpec const&) (usr/bin/../lib/liblldb.so.15+0x268b9dc) ``` Our workaround was to set `set target.parallel-module-load ` to `false` to avoid the crash. ## Background PlatformAndroid creates two different classes with one stateful adb connection shared between the two -- one through AdbClient and another through AdbClient::SyncService. The connection management and state is complex, and seems to be responsible for the segfault we are seeing. The AdbClient code resets these connections at times, and re-establishes connections if they are not active. Similarly, PlatformAndroid caches its SyncService, which uses an AdbClient class, but the SyncService puts its connection into a different 'sync' state that is incompatible with a standard connection. ## Changes in this diff * This diff refactors the code to (hopefully) have clearer ownership of the connection, clearer separation of AdbClient and SyncService by making a new class for clearer separations of concerns, called AdbSyncService. * New unit tests are added * Additional logs were added (see https://github.com/llvm/llvm-project/pull/145382#issuecomment-3055535017 for details)
95 lines
2.7 KiB
C++
95 lines
2.7 KiB
C++
//===-- PlatformAndroid.h ---------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLDB_SOURCE_PLUGINS_PLATFORM_ANDROID_PLATFORMANDROID_H
|
|
#define LLDB_SOURCE_PLUGINS_PLATFORM_ANDROID_PLATFORMANDROID_H
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "Plugins/Platform/Linux/PlatformLinux.h"
|
|
|
|
#include "AdbClient.h"
|
|
|
|
namespace lldb_private {
|
|
namespace platform_android {
|
|
|
|
class PlatformAndroid : public platform_linux::PlatformLinux {
|
|
public:
|
|
PlatformAndroid(bool is_host);
|
|
|
|
static void Initialize();
|
|
|
|
static void Terminate();
|
|
|
|
// lldb_private::PluginInterface functions
|
|
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);
|
|
|
|
static void DebuggerInitialize(lldb_private::Debugger &debugger);
|
|
|
|
static llvm::StringRef GetPluginNameStatic(bool is_host) {
|
|
return is_host ? Platform::GetHostPlatformName() : "remote-android";
|
|
}
|
|
|
|
static llvm::StringRef GetPluginDescriptionStatic(bool is_host);
|
|
|
|
llvm::StringRef GetPluginName() override {
|
|
return GetPluginNameStatic(IsHost());
|
|
}
|
|
|
|
// lldb_private::Platform functions
|
|
|
|
Status ConnectRemote(Args &args) override;
|
|
|
|
Status GetFile(const FileSpec &source, const FileSpec &destination) override;
|
|
|
|
Status PutFile(const FileSpec &source, const FileSpec &destination,
|
|
uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override;
|
|
|
|
uint32_t GetSdkVersion();
|
|
|
|
bool GetRemoteOSVersion() override;
|
|
|
|
Status DisconnectRemote() override;
|
|
|
|
uint32_t GetDefaultMemoryCacheLineSize() override;
|
|
|
|
protected:
|
|
const char *GetCacheHostname() override;
|
|
|
|
Status DownloadModuleSlice(const FileSpec &src_file_spec,
|
|
const uint64_t src_offset, const uint64_t src_size,
|
|
const FileSpec &dst_file_spec) override;
|
|
|
|
Status DownloadSymbolFile(const lldb::ModuleSP &module_sp,
|
|
const FileSpec &dst_file_spec) override;
|
|
|
|
llvm::StringRef
|
|
GetLibdlFunctionDeclarations(lldb_private::Process *process) override;
|
|
|
|
typedef std::unique_ptr<AdbClient> AdbClientUP;
|
|
virtual AdbClientUP GetAdbClient(Status &error);
|
|
|
|
std::string GetRunAs();
|
|
|
|
public:
|
|
virtual llvm::StringRef GetPropertyPackageName();
|
|
|
|
protected:
|
|
virtual std::unique_ptr<AdbSyncService> GetSyncService(Status &error);
|
|
|
|
private:
|
|
std::string m_device_id;
|
|
uint32_t m_sdk_version;
|
|
};
|
|
|
|
} // namespace platform_android
|
|
} // namespace lldb_private
|
|
|
|
#endif // LLDB_SOURCE_PLUGINS_PLATFORM_ANDROID_PLATFORMANDROID_H
|