Fix exception safety in subprocess
This commit is contained in:
parent
aa4e3c7c08
commit
76dc5cbba8
@ -26,44 +26,54 @@ constexpr const char* openmode = "r";
|
||||
using std::string;
|
||||
|
||||
namespace cpputils {
|
||||
//TODO Exception safety
|
||||
|
||||
namespace {
|
||||
FILE *_call(const string &command) {
|
||||
FILE *subprocess = popen(command.c_str(), openmode);
|
||||
if (!subprocess)
|
||||
{
|
||||
throw std::runtime_error("Error starting subprocess "+command + ". Errno: " + std::to_string(errno));
|
||||
}
|
||||
return subprocess;
|
||||
}
|
||||
class SubprocessHandle final {
|
||||
public:
|
||||
SubprocessHandle(const string &command)
|
||||
: _subprocess(popen(command.c_str(), openmode)) {
|
||||
if (!_subprocess) {
|
||||
throw std::runtime_error("Error starting subprocess " + command + ". Errno: " + std::to_string(errno));
|
||||
}
|
||||
}
|
||||
|
||||
string _getOutput(FILE *subprocess) {
|
||||
string output;
|
||||
char buffer[1024];
|
||||
while(fgets(buffer, sizeof(buffer), subprocess) != nullptr) {
|
||||
output += buffer;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
~SubprocessHandle() {
|
||||
if (_subprocess != nullptr) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
string getOutput() {
|
||||
string output;
|
||||
char buffer[1024];
|
||||
while (fgets(buffer, sizeof(buffer), _subprocess) != nullptr) {
|
||||
output += buffer;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
int close() {
|
||||
auto returncode = pclose(_subprocess);
|
||||
_subprocess = nullptr;
|
||||
if (returncode == -1) {
|
||||
throw std::runtime_error("Error calling pclose. Errno: " + std::to_string(errno));
|
||||
}
|
||||
if (!WIFEXITED(returncode)) {
|
||||
// WEXITSTATUS is only valid if WIFEXITED is 0.
|
||||
throw std::runtime_error("WIFEXITED returned " + std::to_string(WIFEXITED(returncode)));
|
||||
}
|
||||
return WEXITSTATUS(returncode);
|
||||
}
|
||||
|
||||
private:
|
||||
FILE *_subprocess;
|
||||
};
|
||||
|
||||
int _close(FILE *subprocess) {
|
||||
auto returncode = pclose(subprocess);
|
||||
if(returncode == -1) {
|
||||
throw std::runtime_error("Error calling pclose. Errno: " + std::to_string(errno));
|
||||
}
|
||||
if (!WIFEXITED(returncode)) {
|
||||
// WEXITSTATUS is only valid if WIFEXITED is 0.
|
||||
throw std::runtime_error("WIFEXITED returned " + std::to_string(WIFEXITED(returncode)));
|
||||
}
|
||||
return WEXITSTATUS(returncode);
|
||||
}
|
||||
}
|
||||
|
||||
SubprocessResult Subprocess::call(const string &command) {
|
||||
FILE *subprocess = _call(command);
|
||||
string output = _getOutput(subprocess);
|
||||
int exitcode = _close(subprocess);
|
||||
SubprocessHandle subprocess(command);
|
||||
string output = subprocess.getOutput();
|
||||
int exitcode = subprocess.close();
|
||||
|
||||
return SubprocessResult {output, exitcode};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user