Skip to content
Snippets Groups Projects
Commit 459c17bc authored by Jason Hiser's avatar Jason Hiser :tractor:
Browse files

fixed deadlock in pipe code

parent ac13ebc8
No related branches found
No related tags found
No related merge requests found
#ifndef cmdstr_hpp
#define cmdstr_hpp
/*BINFMTCXX: -std=c++11 -Wall -Werror
*/
#include <spawn.h> // see manpages-posix-dev
#include <spawn.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -14,19 +11,45 @@
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <array>
using namespace std;
static inline pair<string,int> command_to_string( const string& command)
{
auto ret=string();
int exit_code=0;
int cout_pipe[2];
int cerr_pipe[2];
posix_spawn_file_actions_t action;
if(pipe(cout_pipe) || pipe(cerr_pipe))
cout << "pipe returned an error.\n";
const auto pipe_closer = function<void(int*)>([](int *p_pipefd) -> void
{
const auto pipe = *p_pipefd;
close(pipe);
delete p_pipefd;
});
using PipeFD_t = unique_ptr<int,decltype(pipe_closer)>;
const auto pipe_opener = [&]() -> vector<PipeFD_t>
{
auto pipe_fds = array<int,2>();
if(pipe( pipe_fds.data()))
{
const auto err_str = string(strerror(errno));
throw runtime_error("Cannot open pipe: " + err_str);
}
auto ret = vector<PipeFD_t>();
// PipeFD_t p(new int(pipe_fds[0]), pipe_closer);
// ret.push_back(move(p));
ret.push_back({new int(pipe_fds[0]), pipe_closer});
ret.push_back({new int(pipe_fds[1]), pipe_closer});
return ret;
};
auto cout_pipe_vec = pipe_opener();
auto cerr_pipe_vec = pipe_opener();
const auto cout_pipe = vector<int>{*(cout_pipe_vec[0]), *(cout_pipe_vec[1])};
const auto cerr_pipe = vector<int>{*(cerr_pipe_vec[0]), *(cerr_pipe_vec[1])};
posix_spawn_file_actions_init(&action);
posix_spawn_file_actions_addclose(&action, cout_pipe[0]);
......@@ -37,8 +60,6 @@ static inline pair<string,int> command_to_string( const string& command)
posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
posix_spawn_file_actions_addclose(&action, cerr_pipe[1]);
// string command = "echo bla"; // example #1
// string command = "pgmcrater -width 64 -height 9 |pgmtopbm |pnmtoplainpnm";
vector<char> argsmem[] = {{'s', 'h', '\0'}, {'-', 'c', '\0'}}; // allows non-const access to literals
char *args[] = {&argsmem[0][0], &argsmem[1][0],const_cast<char*>(command.c_str()),nullptr};
......@@ -46,23 +67,23 @@ static inline pair<string,int> command_to_string( const string& command)
if(posix_spawnp(&pid, args[0], &action, NULL, args, environ) != 0)
cout << "posix_spawnp failed with error: " << strerror(errno) << "\n";
close(cout_pipe[1]), close(cerr_pipe[1]); // close child-side of pipes
cout_pipe_vec[1].reset();
cerr_pipe_vec[1].reset(); // close child-side of pipes
// Read from pipes
string buffer(1024,' ');
std::vector<pollfd> plist = { {cout_pipe[0],POLLIN}, {cerr_pipe[0],POLLIN} };
vector<pollfd> plist = { {cout_pipe[0],POLLIN}, {cerr_pipe[0],POLLIN} };
for ( int rval; (rval=poll(&plist[0],plist.size(),/*timeout*/-1))>0; )
{
if ( plist[0].revents&POLLIN) {
if ( plist[0].revents&POLLIN)
{
const auto bytes_read = read(cout_pipe[0], &buffer[0], buffer.length());
// cout << "read " << bytes_read << " bytes from stdout.\n";
// cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n";
ret += buffer.substr(0, static_cast<size_t>(bytes_read));
}
else if ( plist[1].revents&POLLIN ) {
else if ( plist[1].revents&POLLIN )
{
const auto bytes_read = read(cerr_pipe[0], &buffer[0], buffer.length());
// cout << "read " << bytes_read << " bytes from stderr.\n";
// cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n";
ret += buffer.substr(0, static_cast<size_t>(bytes_read));
}
else
......@@ -85,4 +106,5 @@ static inline int command_to_stream(const string& command, ostream& stream)
return res.second;
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment