Skip to content

Commit 4025693

Browse files
authored
Fix exception when CreateProcessW fails and add test for it (#98)
* Fix exception when `CreateProcessW` fails This change makes the behavior on Windows consistent with the behavior on Linux. * test: Add `test_exception`
1 parent 40cd59c commit 4025693

File tree

3 files changed

+35
-7
lines changed

3 files changed

+35
-7
lines changed

subprocess.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class OSError: public std::runtime_error
148148
{
149149
public:
150150
OSError(const std::string& err_msg, int err_code):
151-
std::runtime_error( err_msg + " : " + std::strerror(err_code) )
151+
std::runtime_error( err_msg + ": " + std::strerror(err_code) )
152152
{}
153153
};
154154

@@ -235,16 +235,15 @@ namespace util
235235
}
236236

237237
#ifdef __USING_WINDOWS__
238-
inline std::string get_last_error()
238+
inline std::string get_last_error(DWORD errorMessageID)
239239
{
240-
DWORD errorMessageID = ::GetLastError();
241240
if (errorMessageID == 0)
242241
return std::string();
243242

244243
LPSTR messageBuffer = nullptr;
245244
size_t size = FormatMessageA(
246245
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
247-
FORMAT_MESSAGE_IGNORE_INSERTS,
246+
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
248247
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
249248
(LPSTR)&messageBuffer, 0, NULL);
250249

@@ -1554,8 +1553,10 @@ inline void Popen::execute_process() noexcept(false)
15541553
&piProcInfo); // receives PROCESS_INFORMATION
15551554

15561555
// If an error occurs, exit the application.
1557-
if (!bSuccess)
1558-
throw OSError("CreateProcessW failed", 0);
1556+
if (!bSuccess) {
1557+
DWORD errorMessageID = ::GetLastError();
1558+
throw CalledProcessError("CreateProcess failed: " + util::get_last_error(errorMessageID), errorMessageID);
1559+
}
15591560

15601561
CloseHandle(piProcInfo.hThread);
15611562

test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
set(test_names test_subprocess test_cat test_env test_err_redirection test_split test_main test_ret_code)
1+
set(test_names test_subprocess test_cat test_env test_err_redirection test_exception test_split test_main test_ret_code)
22
set(test_files env_script.sh write_err.sh write_err.txt)
33

44

test/test_exception.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <cassert>
2+
#include <cstring>
3+
#include <subprocess.hpp>
4+
5+
namespace sp = subprocess;
6+
7+
void test_exception()
8+
{
9+
bool caught = false;
10+
try {
11+
auto p = sp::Popen("invalid_command");
12+
assert(false); // Expected to throw
13+
} catch (sp::CalledProcessError& e) {
14+
#ifdef __USING_WINDOWS__
15+
assert(std::strstr(e.what(), "CreateProcess failed: The system cannot find the file specified."));
16+
#else
17+
assert(std::strstr(e.what(), "execve failed: No such file or directory"));
18+
#endif
19+
caught = true;
20+
}
21+
assert(caught);
22+
}
23+
24+
int main() {
25+
test_exception();
26+
return 0;
27+
}

0 commit comments

Comments
 (0)