Skip to content

Commit 1302159

Browse files
author
Daniel Kroening
authored
Merge pull request #5601 from tautschnig/run-windows-error-reporting
run() Windows error reporting
2 parents 6feef01 + 80647dd commit 1302159

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

src/util/run.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,37 @@ std::wstring quote_windows_arg(const std::wstring &src)
219219
}
220220
#endif
221221

222+
#ifdef _WIN32
223+
// https://stackoverflow.com/a/17387176
224+
// Returns the last Win32 error, in string format. Returns an empty string if
225+
// there is no error.
226+
std::string get_last_error_as_string()
227+
{
228+
// Get the error message, if any.
229+
DWORD error_message_id = GetLastError();
230+
if(error_message_id == 0)
231+
return {};
232+
233+
LPWSTR message_buffer = nullptr;
234+
std::size_t size = FormatMessageW(
235+
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
236+
FORMAT_MESSAGE_IGNORE_INSERTS,
237+
NULL,
238+
error_message_id,
239+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
240+
(LPWSTR)&message_buffer,
241+
0,
242+
NULL);
243+
244+
std::wstring message(message_buffer, size);
245+
246+
// Free the buffer.
247+
LocalFree(message_buffer);
248+
249+
return narrow(message);
250+
}
251+
#endif
252+
222253
int run(
223254
const std::string &what,
224255
const std::vector<std::string> &argv,
@@ -272,12 +303,20 @@ int run(
272303

273304
if(!bSuccess)
274305
{
306+
// obtain the error message before doing further system calls
307+
std::string windows_error = get_last_error_as_string();
308+
275309
if(!std_input.empty())
276310
CloseHandle(siStartInfo.hStdInput);
277311
if(!std_output.empty())
278312
CloseHandle(siStartInfo.hStdOutput);
279313
if(!std_error.empty())
280314
CloseHandle(siStartInfo.hStdError);
315+
316+
// now re-open the file and write the above error message
317+
std::ofstream stderr_stream(std_error);
318+
stderr_stream << windows_error;
319+
281320
return -1;
282321
}
283322

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ SRC += analyses/ai/ai.cpp \
118118
util/prefix_filter.cpp \
119119
util/range.cpp \
120120
util/replace_symbol.cpp \
121+
util/run.cpp \
121122
util/sharing_map.cpp \
122123
util/sharing_node.cpp \
123124
util/simplify_expr.cpp \

unit/util/run.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*******************************************************************\
2+
3+
Module: Unit test for run.h/run.cpp
4+
5+
Author: Michael Tautschnig
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/use_catch.h>
10+
11+
#include <util/run.h>
12+
#include <util/tempfile.h>
13+
14+
#include <fstream>
15+
16+
SCENARIO("run() error reporting", "[core][util][run]")
17+
{
18+
GIVEN("A command invoking a non-existent executable")
19+
{
20+
temporary_filet tmp_stderr("tmp.txt", "");
21+
22+
int result =
23+
run("no-such-binary", {"no-such-binary"}, "", "", tmp_stderr());
24+
25+
THEN("run returns a non-zero exit code")
26+
{
27+
REQUIRE(result != 0);
28+
}
29+
THEN("run provides an error message")
30+
{
31+
std::ifstream read_output{tmp_stderr()};
32+
std::string line;
33+
REQUIRE(std::getline(read_output, line));
34+
#ifdef _WIN32
35+
// strip terminating \r
36+
REQUIRE(
37+
Catch::trim(line) == "The system cannot find the file specified.");
38+
#else
39+
REQUIRE(
40+
line == "execvp no-such-binary failed: No such file or directory");
41+
#endif
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)