Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[vscode] Improve runInTerminal and support linux
Depends on D93874. runInTerminal was using --wait-for, but it was some problems because it uses process polling looking for a single instance of the debuggee: - it gets to know of the target late, which renders breakpoints in the main function almost impossible - polling might fail if there are already other processes with the same name - polling might also fail on some linux machine, as it's implemented with the ps command, and the ps command's args and output are not standard everywhere As a better way to implement this so that it works well on Darwin and Linux, I'm using now the following process: - lldb-vscode notices the runInTerminal, so it spawns lldb-vscode with a special flag --launch-target <target>. This flags tells lldb-vscode to wait to be attached and then it execs the target program. I'm using lldb-vscode itself to do this, because it makes finding the launcher program easier. Also no CMAKE INSTALL scripts are needed. - Besides this, the debugger creates a temporary FIFO file where the launcher program will write its pid to. That way the debugger will be sure of which program to attach. - Once attach happend, the debugger creates a second temporary file to notify the launcher program that it has been attached, so that it can then exec. I'm using this instead of using a signal or a similar mechanism because I don't want the launcher program to wait indefinitely to be attached in case the debugger crashed. That would pollute the process list with a lot of hanging processes. Instead, I'm setting a 20 seconds timeout (that's an overkill) and the launcher program seeks in intervals the second tepmorary file. Some notes: - I preferred not to use sockets because it requires a lot of code and I only need a pid. It would also require a lot of code when windows support is implemented. - I didn't add Windows support, as I don't have a windows machine, but adding support for it should be easy, as the FIFO file can be implemented with a named pipe, which is standard on Windows and works pretty much the same way. The existing test which didn't pass on Linux, now passes. Differential Revision: https://reviews.llvm.org/D93951
- Loading branch information
1 parent
71af5a1
commit 0f0462c
Showing
13 changed files
with
779 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//===-- FifoFiles.cpp -------------------------------------------*- 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#if !defined(WIN32) | ||
#include <sys/stat.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
#endif | ||
|
||
#include <chrono> | ||
#include <fstream> | ||
#include <future> | ||
#include <thread> | ||
|
||
#include "llvm/Support/FileSystem.h" | ||
|
||
#include "lldb/lldb-defines.h" | ||
|
||
#include "FifoFiles.h" | ||
|
||
using namespace llvm; | ||
|
||
namespace lldb_vscode { | ||
|
||
FifoFile::FifoFile(StringRef path) : m_path(path) {} | ||
|
||
FifoFile::~FifoFile() { | ||
#if !defined(WIN32) | ||
unlink(m_path.c_str()); | ||
#endif | ||
}; | ||
|
||
Expected<std::shared_ptr<FifoFile>> CreateFifoFile(StringRef path) { | ||
#if defined(WIN32) | ||
return createStringError(inconvertibleErrorCode(), "Unimplemented"); | ||
#else | ||
if (int err = mkfifo(path.data(), 0600)) | ||
return createStringError(std::error_code(err, std::generic_category()), | ||
"Couldn't create fifo file: %s", path.data()); | ||
return std::make_shared<FifoFile>(path); | ||
#endif | ||
} | ||
|
||
FifoFileIO::FifoFileIO(StringRef fifo_file, StringRef other_endpoint_name) | ||
: m_fifo_file(fifo_file), m_other_endpoint_name(other_endpoint_name) {} | ||
|
||
Expected<json::Value> FifoFileIO::ReadJSON(std::chrono::milliseconds timeout) { | ||
// We use a pointer for this future, because otherwise its normal destructor | ||
// would wait for the getline to end, rendering the timeout useless. | ||
Optional<std::string> line; | ||
std::future<void> *future = | ||
new std::future<void>(std::async(std::launch::async, [&]() { | ||
std::ifstream reader(m_fifo_file, std::ifstream::in); | ||
std::string buffer; | ||
std::getline(reader, buffer); | ||
if (!buffer.empty()) | ||
line = buffer; | ||
})); | ||
if (future->wait_for(timeout) == std::future_status::timeout || | ||
!line.hasValue()) | ||
return createStringError(inconvertibleErrorCode(), | ||
"Timed out trying to get messages from the " + | ||
m_other_endpoint_name); | ||
delete future; | ||
return json::parse(*line); | ||
} | ||
|
||
Error FifoFileIO::SendJSON(const json::Value &json, | ||
std::chrono::milliseconds timeout) { | ||
bool done = false; | ||
std::future<void> *future = | ||
new std::future<void>(std::async(std::launch::async, [&]() { | ||
std::ofstream writer(m_fifo_file, std::ofstream::out); | ||
writer << JSONToString(json) << std::endl; | ||
done = true; | ||
})); | ||
if (future->wait_for(timeout) == std::future_status::timeout || !done) { | ||
return createStringError(inconvertibleErrorCode(), | ||
"Timed out trying to send messages to the " + | ||
m_other_endpoint_name); | ||
} | ||
delete future; | ||
return Error::success(); | ||
} | ||
|
||
} // namespace lldb_vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//===-- FifoFiles.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_TOOLS_LLDB_VSCODE_FIFOFILES_H | ||
#define LLDB_TOOLS_LLDB_VSCODE_FIFOFILES_H | ||
|
||
#include "llvm/Support/Error.h" | ||
|
||
#include "JSONUtils.h" | ||
|
||
namespace lldb_vscode { | ||
|
||
/// Struct that controls the life of a fifo file in the filesystem. | ||
/// | ||
/// The file is destroyed when the destructor is invoked. | ||
struct FifoFile { | ||
FifoFile(llvm::StringRef path); | ||
|
||
~FifoFile(); | ||
|
||
std::string m_path; | ||
}; | ||
|
||
/// Create a fifo file in the filesystem. | ||
/// | ||
/// \param[in] path | ||
/// The path for the fifo file. | ||
/// | ||
/// \return | ||
/// A \a std::shared_ptr<FifoFile> if the file could be created, or an | ||
/// \a llvm::Error in case of failures. | ||
llvm::Expected<std::shared_ptr<FifoFile>> CreateFifoFile(llvm::StringRef path); | ||
|
||
class FifoFileIO { | ||
public: | ||
/// \param[in] fifo_file | ||
/// The path to an input fifo file that exists in the file system. | ||
/// | ||
/// \param[in] other_endpoint_name | ||
/// A human readable name for the other endpoint that will communicate | ||
/// using this file. This is used for error messages. | ||
FifoFileIO(llvm::StringRef fifo_file, llvm::StringRef other_endpoint_name); | ||
|
||
/// Read the next JSON object from the underlying input fifo file. | ||
/// | ||
/// The JSON object is expected to be a single line delimited with \a | ||
/// std::endl. | ||
/// | ||
/// \return | ||
/// An \a llvm::Error object indicating the success or failure of this | ||
/// operation. Failures arise if the timeout is hit, the next line of text | ||
/// from the fifo file is not a valid JSON object, or is it impossible to | ||
/// read from the file. | ||
llvm::Expected<llvm::json::Value> ReadJSON(std::chrono::milliseconds timeout); | ||
|
||
/// Serialize a JSON object and write it to the underlying output fifo file. | ||
/// | ||
/// \param[in] json | ||
/// The JSON object to send. It will be printed as a single line delimited | ||
/// with \a std::endl. | ||
/// | ||
/// \param[in] timeout | ||
/// A timeout for how long we should until for the data to be consumed. | ||
/// | ||
/// \return | ||
/// An \a llvm::Error object indicating whether the data was consumed by | ||
/// a reader or not. | ||
llvm::Error SendJSON( | ||
const llvm::json::Value &json, | ||
std::chrono::milliseconds timeout = std::chrono::milliseconds(20000)); | ||
|
||
private: | ||
std::string m_fifo_file; | ||
std::string m_other_endpoint_name; | ||
}; | ||
|
||
} // namespace lldb_vscode | ||
|
||
#endif // LLDB_TOOLS_LLDB_VSCODE_FIFOFILES_H |
Oops, something went wrong.