Skip to content

Commit

Permalink
Capture stdout and stderr separately in task results
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloop committed Jan 15, 2018
1 parent ba766e3 commit 467a7df
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 20 deletions.
10 changes: 7 additions & 3 deletions src/config/task_results.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,13 @@ struct task_results {
*/
std::string error_message;
/**
* Output as taken from stdout and stderr.
* Output as taken from stdout.
*/
std::string output;
std::string output_stdout;
/**
* Output as taken from stderr.
*/
std::string output_stderr;
/**
* Pointer to @ref sandbox_results for external task results.
* Default: nullptr (other types of tasks)
Expand All @@ -121,7 +125,7 @@ struct task_results {
/**
* Constructor with default values initiazation.
*/
task_results() : status(task_status::OK), error_message(), output(), sandbox_status(nullptr)
task_results() : status(task_status::OK), error_message(), output_stdout(), output_stderr(), sandbox_status(nullptr)
{
}

Expand Down
11 changes: 9 additions & 2 deletions src/job/job_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,15 @@ void job_evaluator::push_result()
node["error_message"] = i.second->error_message;
}

if (!i.second->output.empty()) {
node["output"] = i.second->output;
if (!i.second->output_stdout.empty() || !i.second->output_stderr.empty()) {
YAML::Node output_node;
if (!i.second->output_stdout.empty()) {
output_node["stdout"] = i.second->output_stdout;
}
if (!i.second->output_stderr.empty()) {
output_node["stderr"] = i.second->output_stderr;
}
node["output"] = output_node;
}

auto &sandbox = i.second->sandbox_status;
Expand Down
28 changes: 17 additions & 11 deletions src/tasks/external_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ std::shared_ptr<task_results> external_task::run()
std::unique_ptr<sandbox_results>(new sandbox_results(sandbox_->run(task_meta_->binary, task_meta_->cmd_args)));

// get output from stdout and stderr
res->output = get_results_output();
get_results_output(res);

sandbox_fini();

Expand Down Expand Up @@ -125,10 +125,8 @@ fs::path external_task::find_path_outside_sandbox(std::string file)
return helpers::find_path_outside_sandbox(file, sandbox_config_->chdir, limits_->bound_dirs);
}

std::string external_task::get_results_output()
void external_task::get_results_output(std::shared_ptr<task_results> result)
{
std::string result;

if (sandbox_config_->output) {
size_t count = worker_config_->get_max_output_length();
std::string result_stdout(count, 0);
Expand All @@ -144,13 +142,23 @@ std::string external_task::get_results_output()
std_out.read(&result_stdout[0], count);
std_err.read(&result_stderr[0], count);

// if there was something in one of the files, write it to the result
if (std_out.gcount() != 0 || std_err.gcount() != 0) {
result = result_stdout.substr(0, std_out.gcount()) + result_stderr.substr(0, std_err.gcount());
// if there was something in stdout, write it to result
if (std_out.gcount() != 0) {
result_stdout = result_stdout.substr(0, std_out.gcount());
// filter non printable result
helpers::filter_non_printable_chars(result_stdout);
// write to result structure
result->output_stdout = result_stdout;
}

// filter non printable result
helpers::filter_non_printable_chars(result);
// if there was something in stderr, write it to result
if (std_err.gcount() != 0) {
result_stderr = result_stderr.substr(0, std_err.gcount());
// filter non printable result
helpers::filter_non_printable_chars(result_stderr);
// write to result structure
result->output_stderr = result_stderr;
}

// delete produced files
try {
Expand All @@ -164,8 +172,6 @@ std::string external_task::get_results_output()
logger_->warn("Temporary sandbox output files not cleaned properly: {}", e.what());
}
}

return result;
}

void external_task::make_binary_executable(std::string binary)
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/external_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ class external_task : public task_base
void results_output_init();
/**
* Get configuration limited content of the stdout and stderr and return it.
* @return text which was produced by sandboxed program on stdout and stderr
* @param result to which stdout and err will be assigned
*/
std::string get_results_output();
void get_results_output(std::shared_ptr<task_results> result);

/** Worker default configuration */
std::shared_ptr<worker_config> worker_config_;
Expand Down
2 changes: 1 addition & 1 deletion src/tasks/internal/exists_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ std::shared_ptr<task_results> exists_task::run()
if (!fs::exists(file)) {
result->status = task_status::FAILED;
result->error_message = "File/folder '" + file + "' cannot be found";
result->output = task_meta_->cmd_args[0];
result->output_stderr = task_meta_->cmd_args[0];
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/exists_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,5 @@ TEST_F(exists_task_test, file_not_exists)
auto results = task->run();
ASSERT_EQ(task_status::FAILED, results->status);
ASSERT_TRUE(results->error_message.find("cannot be found") != std::string::npos);
ASSERT_EQ("failure message", results->output);
ASSERT_EQ("failure message", results->output_stderr);
}

0 comments on commit 467a7df

Please sign in to comment.