Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save yohm/5c34fc10d8e7530b3d1d5d055bdcb0b4 to your computer and use it in GitHub Desktop.
Save yohm/5c34fc10d8e7530b3d1d5d055bdcb0b4 to your computer and use it in GitHub Desktop.
invoking a subprocess using fork&exec in a temporal working directory with redirected stdout and stderr and timeout
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <vector>
#include <string>
int system_with_timeout(std::vector<std::string> args, int timeout, std::string dirname) {
pid_t pid;
if ((pid = fork()) == 0) {
char abspath[PATH_MAX];
realpath( args[0].c_str(), abspath );
char** arg = NULL;
arg = new char*[args.size() + 1 ];
for( size_t i=0; i<args.size(); i++ ) {
if( i == 0 ) {
arg[i] = abspath;
}
else {
arg[i] = (char*) args[i].c_str();
}
}
arg[ args.size() ] = NULL;
int ret = mkdir( dirname.c_str(), 0700 );
if( ret != 0 ) {
std::cerr << "failed to create directory : " << dirname << std::endl;
exit(1);
}
ret = chdir( dirname.c_str() );
if( ret != 0 ) {
std::cerr << "failed to change directory : " << dirname << std::endl;
exit(1);
}
int fd_out = open("_stdout", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
int fd_err = open("_stderr", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
// read only, create a file if not exist, read permission, write permission
dup2( fd_out, 1 );
dup2( fd_err, 2 );
close( fd_out );
close( fd_err );
int rc = execvp( arg[0], (char*const*) arg );
std::cerr << "failed to execute the command. rc : " << rc << std::endl;
exit(1);
}
else if (pid > 0) {
int status = 0;
time_t begin = std::time(NULL);
while( true ) {
sleep(1);
int ret = waitpid(pid, &status, WNOHANG);
if( ret != 0 ) {
break;
}
double diff = std::difftime( std::time(NULL), begin );
if( diff >= timeout ) {
std::cerr << " sending sigint" << std::endl;
kill( pid, 2 );
}
}
if( WIFEXITED(status) ) {
return WEXITSTATUS(status);
}
else if( WIFSIGNALED(status) ) {
std::cerr << "signaled by signal" << WTERMSIG(status) << std::endl;
return -1;
}
else {
std::cerr << "other" << std::endl;
return -1;
}
}
std::cerr << "failed to fork" << std::endl;
return -1;
}
int main(int argc, char *argv[])
{
std::vector<std::string> args;
args.push_back("/usr/bin/ruby");
args.push_back("-e");
args.push_back("puts 'hello'; $stderr.puts 'world'; sleep 3");
int rc = system_with_timeout( args, 1 , "temp");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment