chigraph  master
Systems programming language written for beginners in LLVM
chi::Subprocess Struct Reference

Provides an platform-independent abstraction for creating subprocesses. More...

#include <chi/Support/Subprocess.hpp>

Public Types

using pipeHandler = std::function< void(const char *data, size_t size)>
 The function type for recieving data from pipes.
 

Public Member Functions

 Subprocess (const boost::filesystem::path &pathToExecutable)
 Construct a Subprocess with a path to an executable. More...
 
 ~Subprocess ()
 Wait for the process to exit and close all open handles.
 
Result start ()
 Start the process. More...
 
bool started () const
 Check if the child has started (start() has been called) More...
 
Setup Functions

Setup functions are called after the cosntructor, but before start().

Most of them cannot be called after start(). They are used to set parameters for the program's execution

template<typename ForwardIterator >
void setArguments (const ForwardIterator &begin, const ForwardIterator &end)
 Set the arguments for the program with a begin and end iterator. More...
 
template<typename Range >
void setArguments (Range &&range)
 Set the arguments for the program with a range. More...
 
void setArguments (std::initializer_list< const char *> init)
 Set the arguments for the program with an initializer_list. More...
 
const std::vector< std::string > & arguments () const
 Get the currently set arguments for the program. More...
 
void attachToStdOut (pipeHandler stdOutHandler)
 Attach a function handler to the child stdout. More...
 
void attachToStdErr (pipeHandler stdErrHandler)
 Attach a function handler to the child stderr. More...
 
void attachStringToStdOut (std::string &str)
 Attach a string to stdout. More...
 
void attachStringToStdErr (std::string &str)
 Attach a string to stderr. More...
 
void setWorkingDirectory (boost::filesystem::path newWd)
 Set the working directory of the process. More...
 
Runtime Functions

These functions are called while the process has started (ie after start() is called)

Result pushToStdIn (const char *data, size_t size)
 Pushes data to the stdin stream of the child process. More...
 
Result closeStdIn ()
 Close the STDIN stream (send an EOF) More...
 
bool isStdInClosed () const
 Checks if the stdin is closed. More...
 
void kill ()
 Kill the child process On POSIX, this sends SIGINT. More...
 
void wait ()
 Wait for the process to complete. More...
 
int exitCode ()
 Wait and gets the exit code. More...
 
bool running ()
 Check if the process is still running. More...
 

Detailed Description

Provides an platform-independent abstraction for creating subprocesses.

On OSX and Linux, this uses the POSIX api (pipe(), fork(), exec(), write(), read(), etc) and on windows it uses the win32 API (CreatePipe(), CreateProcess(), ReadFile(), etc)

Usage is you create a Subprocess class:

#ifdef WIN32
"C:\\Windows\\System32\\cmd.exe"
#else
"/bin/sh"
#endif
};

Now you can use any of the Setup Functions (see above). The string we pass to attachStringToStdOut is written from a differnt thread, so it's not safe to acces it until the program has exited.

std::string stdOut;
child.attachStringToStdOut(stdOut);

Once you're sure all youre setup variables are correctly set, start the process. You cannot change any of the setup values once you have called start()

res += child.start();
if (!res) {
std::cerr << res << std::endl;
return 1;
}

Now that it's started, we can write data (if we wish) to stdin:

std::string dataToSend = "echo hello";
res += child.pushToStdIn(dataToSend.data(), dataToSend.size());
if (!res) {
std::cerr << res << std::endl;
return 1;
}
res += child.closeStdIn();
if (!res) {
std::cerr << res << std::endl;
return 1;
}

Now, you can use running() to see if the process has exited yet. We'll just use exitCode() to wait for the process to complete and get its exit code:

int exitCode = child.exitCode();
if (exitCode != 0) {
std::cerr << "Failed run /bin/sh < 'echo hi' with exit code: " << exitCode << std::endl;
return 1;
}

Now that the process has exited, it's safe to use the stdOut string:

std::cout << stdOut << std::endl;
Examples:
SubprocessExample.cpp.

Definition at line 52 of file Subprocess.hpp.

Constructor & Destructor Documentation

◆ Subprocess()

chi::Subprocess::Subprocess ( const boost::filesystem::path &  pathToExecutable)

Construct a Subprocess with a path to an executable.

Precondition
boost::filesystem::is_regular_file(pathToExecutable)

Definition at line 572 of file Subprocess.cpp.

Member Function Documentation

◆ arguments()

const std::vector<std::string>& chi::Subprocess::arguments ( ) const
inline

Get the currently set arguments for the program.

Returns
The arguments

Definition at line 104 of file Subprocess.hpp.

◆ attachStringToStdErr()

void chi::Subprocess::attachStringToStdErr ( std::string &  str)
inline

Attach a string to stderr.

Everything added to the string is appended. This is just a convenicence function, it just calls attachToStdout with a function appending the data to the string.

Parameters
strThe string to append stderr to
Note
Don't try to read from str while the program is running, it could create a race condition.
Precondition
started() == false

Definition at line 146 of file Subprocess.hpp.

References attachToStdErr().

Referenced by chi::compileCToLLVM().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attachStringToStdOut()

void chi::Subprocess::attachStringToStdOut ( std::string &  str)
inline

Attach a string to stdout.

Everything added to the string is appended. This is just a convenicence function, it just calls attachToStdout with a function appending the data to the string.

Parameters
strThe string to append stdout to
Note
Don't try to read from str while the program is running, it could create a race condition.
Precondition
started() == false
Examples:
SubprocessExample.cpp.

Definition at line 135 of file Subprocess.hpp.

References attachToStdOut().

Referenced by chi::compileCToLLVM().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attachToStdErr()

void chi::Subprocess::attachToStdErr ( pipeHandler  stdErrHandler)
inline

Attach a function handler to the child stderr.

Every time data is recieved through the stderr pipe of the child, it will be sent to this handler

Parameters
stdErrHandlerThe handler
Note
stdErrHandler will exclusively be called from another thread.
Precondition
started() == false

Definition at line 122 of file Subprocess.hpp.

References started().

Referenced by attachStringToStdErr().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attachToStdOut()

void chi::Subprocess::attachToStdOut ( pipeHandler  stdOutHandler)
inline

Attach a function handler to the child stdout.

Every time data is recieved through the stdout pipe of the child, it will be sent to this handler

Parameters
stdOutHandlerThe handler
Note
stdOutHandler will exclusively be called from another thread.
Precondition
started() == false

Definition at line 111 of file Subprocess.hpp.

References started().

Referenced by attachStringToStdOut().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ closeStdIn()

Result chi::Subprocess::closeStdIn ( )

Close the STDIN stream (send an EOF)

Returns
The Result
Precondition
!isStdInClosed()
running()
Postcondition
isStdInClosed()

Definition at line 388 of file Subprocess.cpp.

References chi::Result::addEntry().

Referenced by chi::compileCToLLVM(), and started().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exitCode()

int chi::Subprocess::exitCode ( )

Wait and gets the exit code.

Returns
The exit code. 0 for success.
Precondition
started()

Definition at line 534 of file Subprocess.cpp.

Referenced by chi::compileCToLLVM(), and isStdInClosed().

+ Here is the caller graph for this function:

◆ isStdInClosed()

bool chi::Subprocess::isStdInClosed ( ) const
inline

Checks if the stdin is closed.

Returns
true if it is, false otherwise

Definition at line 188 of file Subprocess.hpp.

References exitCode(), kill(), running(), and wait().

+ Here is the call graph for this function:

◆ kill()

void chi::Subprocess::kill ( )

Kill the child process On POSIX, this sends SIGINT.

Precondition
started()

Definition at line 520 of file Subprocess.cpp.

Referenced by isStdInClosed().

+ Here is the caller graph for this function:

◆ pushToStdIn()

Result chi::Subprocess::pushToStdIn ( const char *  data,
size_t  size 
)

Pushes data to the stdin stream of the child process.

Parameters
dataThe pointer to the start of the data
sizeHow long the data is
Precondition
started()
!isStdInClosed()

Definition at line 374 of file Subprocess.cpp.

References chi::Result::addEntry().

Referenced by chi::compileCToLLVM(), and started().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ running()

bool chi::Subprocess::running ( )

Check if the process is still running.

Returns
true if it's still running, false otherwise
Precondition
started()

Definition at line 550 of file Subprocess.cpp.

Referenced by isStdInClosed().

+ Here is the caller graph for this function:

◆ setArguments() [1/3]

template<typename ForwardIterator >
void chi::Subprocess::setArguments ( const ForwardIterator &  begin,
const ForwardIterator &  end 
)
inline

Set the arguments for the program with a begin and end iterator.

Parameters
beginThe start iterator of arguments. Should be an iterator of something converatable to std::string
endThe end iterator. Should be an iterator of something converatable to std::string
Precondition
started() == false

Definition at line 75 of file Subprocess.hpp.

References started().

Referenced by chi::compileCToLLVM(), and setArguments().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setArguments() [2/3]

template<typename Range >
void chi::Subprocess::setArguments ( Range &&  range)
inline

Set the arguments for the program with a range.

Parameters
rangeThe range. Must have begin() and end() functions, which return iterators.
Precondition
started() == false

Definition at line 91 of file Subprocess.hpp.

References setArguments().

+ Here is the call graph for this function:

◆ setArguments() [3/3]

void chi::Subprocess::setArguments ( std::initializer_list< const char *>  init)
inline

Set the arguments for the program with an initializer_list.

Parameters
initthe initializer list
Precondition
started() == false

Definition at line 98 of file Subprocess.hpp.

References setArguments().

+ Here is the call graph for this function:

◆ setWorkingDirectory()

void chi::Subprocess::setWorkingDirectory ( boost::filesystem::path  newWd)
inline

Set the working directory of the process.

Parameters
newWdThe new working directory
Precondition
started() == false

Definition at line 153 of file Subprocess.hpp.

References start().

+ Here is the call graph for this function:

◆ start()

Result chi::Subprocess::start ( )

Start the process.

After this is called, most of the Setup Functions cannot be called anymore

Returns
The Result.
Precondition
started() == false
Postcondition
started()

Definition at line 405 of file Subprocess.cpp.

References chi::Result::addEntry().

Referenced by chi::compileCToLLVM(), and setWorkingDirectory().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ started()

bool chi::Subprocess::started ( ) const
inline

Check if the child has started (start() has been called)

Returns
True if it has, false otherwise

Definition at line 166 of file Subprocess.hpp.

References closeStdIn(), and pushToStdIn().

Referenced by attachToStdErr(), attachToStdOut(), and setArguments().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ wait()

void chi::Subprocess::wait ( )

Wait for the process to complete.

Precondition
started()

Definition at line 525 of file Subprocess.cpp.

Referenced by isStdInClosed().

+ Here is the caller graph for this function:

The documentation for this struct was generated from the following files: