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;
|
using std::string;
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
//TODO Exception safety
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
FILE *_call(const string &command) {
|
class SubprocessHandle final {
|
||||||
FILE *subprocess = popen(command.c_str(), openmode);
|
public:
|
||||||
if (!subprocess)
|
SubprocessHandle(const string &command)
|
||||||
{
|
: _subprocess(popen(command.c_str(), openmode)) {
|
||||||
throw std::runtime_error("Error starting subprocess "+command + ". Errno: " + std::to_string(errno));
|
if (!_subprocess) {
|
||||||
}
|
throw std::runtime_error("Error starting subprocess " + command + ". Errno: " + std::to_string(errno));
|
||||||
return subprocess;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string _getOutput(FILE *subprocess) {
|
~SubprocessHandle() {
|
||||||
string output;
|
if (_subprocess != nullptr) {
|
||||||
char buffer[1024];
|
close();
|
||||||
while(fgets(buffer, sizeof(buffer), subprocess) != nullptr) {
|
}
|
||||||
output += buffer;
|
}
|
||||||
}
|
|
||||||
return output;
|
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) {
|
SubprocessResult Subprocess::call(const string &command) {
|
||||||
FILE *subprocess = _call(command);
|
SubprocessHandle subprocess(command);
|
||||||
string output = _getOutput(subprocess);
|
string output = subprocess.getOutput();
|
||||||
int exitcode = _close(subprocess);
|
int exitcode = subprocess.close();
|
||||||
|
|
||||||
return SubprocessResult {output, exitcode};
|
return SubprocessResult {output, exitcode};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user