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`
This commit is contained in:
Hennadii Stepanov 2024-01-25 06:31:40 +00:00 committed by GitHub
parent 40cd59c097
commit 4025693dec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 7 deletions

View File

@ -148,7 +148,7 @@ class OSError: public std::runtime_error
{
public:
OSError(const std::string& err_msg, int err_code):
std::runtime_error( err_msg + " : " + std::strerror(err_code) )
std::runtime_error( err_msg + ": " + std::strerror(err_code) )
{}
};
@ -235,16 +235,15 @@ namespace util
}
#ifdef __USING_WINDOWS__
inline std::string get_last_error()
inline std::string get_last_error(DWORD errorMessageID)
{
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0)
return std::string();
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&messageBuffer, 0, NULL);
@ -1554,8 +1553,10 @@ inline void Popen::execute_process() noexcept(false)
&piProcInfo); // receives PROCESS_INFORMATION
// If an error occurs, exit the application.
if (!bSuccess)
throw OSError("CreateProcessW failed", 0);
if (!bSuccess) {
DWORD errorMessageID = ::GetLastError();
throw CalledProcessError("CreateProcess failed: " + util::get_last_error(errorMessageID), errorMessageID);
}
CloseHandle(piProcInfo.hThread);

View File

@ -1,4 +1,4 @@
set(test_names test_subprocess test_cat test_env test_err_redirection test_split test_main test_ret_code)
set(test_names test_subprocess test_cat test_env test_err_redirection test_exception test_split test_main test_ret_code)
set(test_files env_script.sh write_err.sh write_err.txt)

27
test/test_exception.cc Normal file
View File

@ -0,0 +1,27 @@
#include <cassert>
#include <cstring>
#include <subprocess.hpp>
namespace sp = subprocess;
void test_exception()
{
bool caught = false;
try {
auto p = sp::Popen("invalid_command");
assert(false); // Expected to throw
} catch (sp::CalledProcessError& e) {
#ifdef __USING_WINDOWS__
assert(std::strstr(e.what(), "CreateProcess failed: The system cannot find the file specified."));
#else
assert(std::strstr(e.what(), "execve failed: No such file or directory"));
#endif
caught = true;
}
assert(caught);
}
int main() {
test_exception();
return 0;
}