|
9 | 9 | #include "DAP.h" |
10 | 10 | #include "JSONUtils.h" |
11 | 11 | #include "LLDBUtils.h" |
| 12 | +#include "OutputRedirector.h" |
12 | 13 | #include "lldb/API/SBBreakpoint.h" |
13 | 14 | #include "lldb/API/SBCommandInterpreter.h" |
14 | 15 | #include "lldb/API/SBCommandReturnObject.h" |
@@ -49,8 +50,8 @@ using namespace lldb_dap; |
49 | 50 |
|
50 | 51 | namespace lldb_dap { |
51 | 52 |
|
52 | | -DAP::DAP(llvm::StringRef path, std::optional<std::ofstream> &log, |
53 | | - ReplMode repl_mode, StreamDescriptor input, StreamDescriptor output) |
| 53 | +DAP::DAP(llvm::StringRef path, std::ofstream *log, ReplMode repl_mode, |
| 54 | + StreamDescriptor input, StreamDescriptor output) |
54 | 55 | : debug_adaptor_path(path), log(log), input(std::move(input)), |
55 | 56 | output(std::move(output)), broadcaster("lldb-dap"), |
56 | 57 | exception_breakpoints(), focus_tid(LLDB_INVALID_THREAD_ID), |
@@ -178,63 +179,55 @@ ExceptionBreakpoint *DAP::GetExceptionBreakpoint(const lldb::break_id_t bp_id) { |
178 | 179 | return nullptr; |
179 | 180 | } |
180 | 181 |
|
181 | | -llvm::Error DAP::ConfigureIO(std::optional<std::FILE *> overrideOut, |
182 | | - std::optional<std::FILE *> overrideErr) { |
| 182 | +llvm::Error DAP::ConfigureIO(std::FILE *overrideOut, std::FILE *overrideErr) { |
183 | 183 | auto *inull = lldb_private::FileSystem::Instance().Fopen( |
184 | 184 | lldb_private::FileSystem::DEV_NULL, "w"); |
185 | 185 | in = lldb::SBFile(inull, true); |
186 | 186 |
|
187 | | - lldb_private::Status status; |
188 | | - status = pout.CreateNew(/*child_process_inherit=*/false); |
189 | | - if (status.Fail()) |
190 | | - return status.takeError(); |
191 | | - status = perr.CreateNew(/*child_process_inherit=*/false); |
192 | | - if (status.Fail()) |
193 | | - return status.takeError(); |
| 187 | + if (auto Error = out.RedirectTo([this](llvm::StringRef output) { |
| 188 | + SendOutput(OutputType::Stdout, output); |
| 189 | + })) |
| 190 | + return Error; |
194 | 191 |
|
195 | 192 | if (overrideOut) { |
196 | | - if (dup2(pout.GetWriteFileDescriptor(), fileno(*overrideOut)) == -1) { |
| 193 | + auto fd = out.GetWriteFileDescriptor(); |
| 194 | + if (auto Error = fd.takeError()) |
| 195 | + return Error; |
| 196 | + |
| 197 | + if (dup2(*fd, fileno(overrideOut)) == -1) |
197 | 198 | return llvm::make_error<llvm::StringError>( |
198 | 199 | llvm::errnoAsErrorCode(), |
199 | | - llvm::formatv("override fd=%d failed", fileno(*overrideOut)) |
| 200 | + llvm::formatv("override fd=%d failed", fileno(overrideOut)) |
200 | 201 | .str() |
201 | 202 | .c_str()); |
202 | | - } |
203 | 203 | } |
204 | 204 |
|
| 205 | + if (auto Error = err.RedirectTo([this](llvm::StringRef output) { |
| 206 | + SendOutput(OutputType::Stderr, output); |
| 207 | + })) |
| 208 | + return Error; |
| 209 | + |
205 | 210 | if (overrideErr) { |
206 | | - if (dup2(perr.GetWriteFileDescriptor(), fileno(*overrideErr)) == -1) { |
| 211 | + auto fd = err.GetWriteFileDescriptor(); |
| 212 | + if (auto Error = fd.takeError()) |
| 213 | + return Error; |
| 214 | + |
| 215 | + if (dup2(*fd, fileno(overrideErr)) == -1) |
207 | 216 | return llvm::make_error<llvm::StringError>( |
208 | 217 | llvm::errnoAsErrorCode(), |
209 | | - llvm::formatv("override fd=%d failed", fileno(*overrideErr)) |
| 218 | + llvm::formatv("override fd=%d failed", fileno(overrideErr)) |
210 | 219 | .str() |
211 | 220 | .c_str()); |
212 | | - } |
213 | 221 | } |
214 | 222 |
|
215 | | - auto forwarder = [&](lldb_private::Pipe &pipe, OutputType outputType) { |
216 | | - char buffer[4098]; |
217 | | - size_t bytes_read; |
218 | | - while (pipe.CanRead()) { |
219 | | - lldb_private::Status error = pipe.ReadWithTimeout( |
220 | | - &buffer, sizeof(buffer), std::chrono::seconds(1), bytes_read); |
221 | | - if (error.Success()) { |
222 | | - // zero bytes returned on EOF. |
223 | | - if (bytes_read == 0) |
224 | | - break; |
225 | | - SendOutput(outputType, llvm::StringRef(buffer, bytes_read)); |
226 | | - } |
227 | | - } |
228 | | - }; |
229 | | - |
230 | | - stdout_forward_thread = |
231 | | - std::thread(forwarder, std::ref(pout), OutputType::Stdout); |
232 | | - stderr_forward_thread = |
233 | | - std::thread(forwarder, std::ref(perr), OutputType::Stderr); |
234 | | - |
235 | 223 | return llvm::Error::success(); |
236 | 224 | } |
237 | 225 |
|
| 226 | +void DAP::StopIO() { |
| 227 | + out.Stop(); |
| 228 | + err.Stop(); |
| 229 | +} |
| 230 | + |
238 | 231 | // Send the JSON in "json_str" to the "out" stream. Correctly send the |
239 | 232 | // "Content-Length:" field followed by the length, followed by the raw |
240 | 233 | // JSON bytes. |
|
0 commit comments