Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --save-as param to record #3576

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/RecordCommand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ RecordCommand RecordCommand::singleton(
" _RR_TRACE_DIR gets ignored.\n"
" Directory name is given name, not the\n"
" application name.\n"
" --save-as=<NAME> Name of the new recording's directory. If\n"
" a recording with that name already exists, normal\n"
" number appending is applied."
" -p --print-trace-dir=<NUM> print trace directory followed by a newline\n"
" to given file descriptor\n"
" --syscall-buffer-sig=<NUM> the signal used for communication with the\n"
Expand Down Expand Up @@ -128,7 +131,7 @@ struct RecordFlags {

int print_trace_dir;

string output_trace_dir;
TraceOutputPath path;

/* Whether to use file-cloning optimization during recording. */
bool use_file_cloning;
Expand Down Expand Up @@ -187,7 +190,7 @@ struct RecordFlags {
use_syscall_buffer(RecordSession::ENABLE_SYSCALL_BUF),
syscall_buffer_size(0),
print_trace_dir(-1),
output_trace_dir(""),
path{"", "", false, false},
use_file_cloning(true),
use_read_cloning(true),
bind_cpu(BIND_CPU),
Expand Down Expand Up @@ -265,6 +268,7 @@ static bool parse_record_arg(vector<string>& args, RecordFlags& flags) {
{ 16, "disable-avx-512", NO_PARAMETER },
{ 17, "asan", NO_PARAMETER },
{ 18, "tsan", NO_PARAMETER },
{ 19, "save-as", HAS_PARAMETER },
{ 'c', "num-cpu-ticks", HAS_PARAMETER },
{ 'h', "chaos", NO_PARAMETER },
{ 'i', "ignore-signal", HAS_PARAMETER },
Expand All @@ -276,6 +280,7 @@ static bool parse_record_arg(vector<string>& args, RecordFlags& flags) {
{ 'u', "cpu-unbound", NO_PARAMETER },
{ 'v', "env", HAS_PARAMETER },
{ 'w', "wait", NO_PARAMETER }};

ParsedOption opt;
auto args_copy = args;
if (!Command::parse_option(args_copy, options, &opt)) {
Expand Down Expand Up @@ -310,7 +315,8 @@ static bool parse_record_arg(vector<string>& args, RecordFlags& flags) {
flags.print_trace_dir = opt.int_value;
break;
case 'o':
flags.output_trace_dir = opt.value;
flags.path.output_trace_dir = opt.value;
flags.path.usr_provided_outdir = true;
break;
case 0:
flags.use_read_cloning = false;
Expand Down Expand Up @@ -478,6 +484,10 @@ static bool parse_record_arg(vector<string>& args, RecordFlags& flags) {
case 18:
flags.tsan = true;
break;
case 19:
flags.path.name = opt.value;
flags.path.usr_provided_name = true;
break;
case 's':
flags.always_switch = true;
break;
Expand Down Expand Up @@ -661,11 +671,11 @@ static void* repeat_SIGTERM(__attribute__((unused)) void* p) {

static WaitStatus record(const vector<string>& args, const RecordFlags& flags) {
LOG(info) << "Start recording...";

DEBUG_ASSERT(!flags.path.name.empty() && !flags.path.output_trace_dir.empty() && "No output dir or trace dir name set");
auto session = RecordSession::create(
args, flags.extra_env, flags.disable_cpuid_features,
args, flags.extra_env, flags.disable_cpuid_features, flags.path,
flags.use_syscall_buffer, flags.syscallbuf_desched_sig,
flags.bind_cpu, flags.output_trace_dir,
flags.bind_cpu,
flags.trace_id.get(),
flags.stap_sdt, flags.unmap_vdso, flags.asan, flags.tsan);
setup_session_from_flags(*session, flags);
Expand Down Expand Up @@ -696,7 +706,7 @@ static WaitStatus record(const vector<string>& args, const RecordFlags& flags) {
bool done_initial_exec = session->done_initial_exec();
step_result = session->record_step();
// Only create latest-trace symlink if --output-trace-dir is not being used
if (!done_initial_exec && session->done_initial_exec() && flags.output_trace_dir.empty()) {
if (!done_initial_exec && session->done_initial_exec() && flags.path.output_trace_dir.empty()) {
session->trace_writer().make_latest_trace();
}
if (term_requested) {
Expand Down Expand Up @@ -857,6 +867,16 @@ int RecordCommand::run(vector<string>& args) {
flags.extra_env.push_back(padding);
}

if(flags.path.name.empty()) {
flags.path.name = args[0];
flags.path.usr_provided_name = false;
}

if(flags.path.output_trace_dir.empty()) {
flags.path.usr_provided_outdir = false;
flags.path.output_trace_dir = trace_save_dir();
}

WaitStatus status = record(args, flags);

// Everything should have been cleaned up by now.
Expand Down
8 changes: 4 additions & 4 deletions src/RecordSession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2281,10 +2281,10 @@ static string lookup_by_path(const string& name) {
/*static*/ RecordSession::shr_ptr RecordSession::create(
const vector<string>& argv, const vector<string>& extra_env,
const DisableCPUIDFeatures& disable_cpuid_features,
const TraceOutputPath& path_info,
SyscallBuffering syscallbuf,
unsigned char syscallbuf_desched_sig,
BindCPU bind_cpu,
const string& output_trace_dir,
const TraceUuid* trace_id,
bool use_audit,
bool unmap_vdso,
Expand Down Expand Up @@ -2417,7 +2417,7 @@ static string lookup_by_path(const string& name) {
shr_ptr session(
new RecordSession(full_path, argv, env, disable_cpuid_features,
syscallbuf, syscallbuf_desched_sig, bind_cpu,
output_trace_dir, trace_id, use_audit, unmap_vdso));
path_info, trace_id, use_audit, unmap_vdso));
session->excluded_ranges_ = std::move(exe_info.sanitizer_exclude_memory_ranges);
session->fixed_global_exclusion_range_ = std::move(exe_info.fixed_global_exclusion_range);
return session;
Expand All @@ -2430,11 +2430,11 @@ RecordSession::RecordSession(const std::string& exe_path,
SyscallBuffering syscallbuf,
int syscallbuf_desched_sig,
BindCPU bind_cpu,
const string& output_trace_dir,
const TraceOutputPath& path,
const TraceUuid* trace_id,
bool use_audit,
bool unmap_vdso)
: trace_out(argv[0], output_trace_dir, ticks_semantics_),
: trace_out(path, ticks_semantics_),
scheduler_(*this),
trace_id(trace_id),
disable_cpuid_features_(disable_cpuid_features),
Expand Down
7 changes: 3 additions & 4 deletions src/RecordSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Session.h"
#include "ThreadGroup.h"
#include "TraceFrame.h"
#include "TraceStream.h"
#include "WaitStatus.h"

namespace rr {
Expand Down Expand Up @@ -63,10 +64,10 @@ class RecordSession final : public Session {
const std::vector<std::string>& argv,
const std::vector<std::string>& extra_env,
const DisableCPUIDFeatures& features,
const TraceOutputPath& path_info,
SyscallBuffering syscallbuf = ENABLE_SYSCALL_BUF,
unsigned char syscallbuf_desched_sig = SIGPWR,
BindCPU bind_cpu = BIND_CPU,
const std::string& output_trace_dir = "",
const TraceUuid* trace_id = nullptr,
bool use_audit = false,
bool unmap_vdso = false,
Expand Down Expand Up @@ -214,7 +215,7 @@ class RecordSession final : public Session {
SyscallBuffering syscallbuf,
int syscallbuf_desched_sig,
BindCPU bind_cpu,
const std::string& output_trace_dir,
const TraceOutputPath& path_info,
const TraceUuid* trace_id,
bool use_audit,
bool unmap_vdso);
Expand Down Expand Up @@ -274,8 +275,6 @@ class RecordSession final : public Session {
*/
std::map<pid_t, RecordTask*> detached_task_map;

std::string output_trace_dir;

bool use_audit_;
bool unmap_vdso_;
};
Expand Down
48 changes: 27 additions & 21 deletions src/TraceStream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1281,31 +1281,16 @@ bool TraceReader::read_raw_data_metadata_for_frame(RawDataMetadata& d) {
return true;
}

static string make_trace_dir(const string& exe_path, const string& output_trace_dir) {
if (!output_trace_dir.empty()) {
// save trace dir in given output trace dir with option -o
int ret = mkdir(output_trace_dir.c_str(), S_IRWXU | S_IRWXG);
if (ret == 0) {
return output_trace_dir;
}
if (EEXIST == errno) {
CLEAN_FATAL() << "Trace directory `" << output_trace_dir << "' already exists.";
} else if (EACCES == errno) {
CLEAN_FATAL() << "Permission denied to create trace directory `" << output_trace_dir << "'";
} else {
FATAL() << "Unable to create trace directory `" << output_trace_dir << "'";
}
} else {
// save trace dir set in _RR_TRACE_DIR or in the default trace dir
ensure_dir(trace_save_dir(), "trace directory", S_IRWXU);
static string create_unique_dir(const TraceOutputPath& path) {
ensure_dir(path.output_trace_dir, "trace directory", S_IRWXU);

// Find a unique trace directory name.
int nonce = 0;
int ret;
string dir;
do {
stringstream ss;
ss << trace_save_dir() << "/" << basename(exe_path.c_str()) << "-"
ss << path.output_trace_dir << "/" << basename(path.name.c_str()) << "-"
<< nonce++;
dir = ss.str();
ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG);
Expand All @@ -1316,6 +1301,28 @@ static string make_trace_dir(const string& exe_path, const string& output_trace_
}

return dir;
}

static string make_trace_dir(const TraceOutputPath& path) {
if (path.usr_provided_outdir) {
// save trace dir in given output trace dir with option -o
int ret = mkdir(path.output_trace_dir.c_str(), S_IRWXU | S_IRWXG);
if(path.usr_provided_name) {
return create_unique_dir(path);
}
if (ret == 0) {
return path.output_trace_dir;
}
if (EEXIST == errno) {
CLEAN_FATAL() << "Trace directory `" << path.output_trace_dir << "' already exists.";
} else if (EACCES == errno) {
CLEAN_FATAL() << "Permission denied to create trace directory `" << path.output_trace_dir << "'";
} else {
FATAL() << "Unable to create trace directory `" << path.output_trace_dir << "'";
}
} else {
// save trace dir set in _RR_TRACE_DIR or in the default trace dir
return create_unique_dir(path);
}

return ""; // not reached
Expand All @@ -1324,10 +1331,9 @@ static string make_trace_dir(const string& exe_path, const string& output_trace_
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

TraceWriter::TraceWriter(const std::string& file_name,
const string& output_trace_dir,
TraceWriter::TraceWriter(const TraceOutputPath& trace_output,
TicksSemantics ticks_semantics_)
: TraceStream(make_trace_dir(file_name, output_trace_dir),
: TraceStream(make_trace_dir(trace_output),
// Somewhat arbitrarily start the
// global time from 1.
1),
Expand Down
4 changes: 2 additions & 2 deletions src/TraceStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "TraceFrame.h"
#include "TraceTaskEvent.h"
#include "remote_ptr.h"
#include "util.h"

namespace rr {

Expand Down Expand Up @@ -249,8 +250,7 @@ class TraceWriter : public TraceStream {
* The trace name is determined by |file_name| and _RR_TRACE_DIR (if set)
* or by setting -o=<OUTPUT_TRACE_DIR>.
*/
TraceWriter(const std::string& file_name,
const string& output_trace_dir, TicksSemantics ticks_semantics);
TraceWriter(const TraceOutputPath& path, TicksSemantics ticks_semantics);

/**
* Called after the calling thread is actually bound to |bind_to_cpu|.
Expand Down
7 changes: 7 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,13 @@ inline unsigned long long dczid_el0_block_size(void) {
#endif
}

struct TraceOutputPath {
std::string output_trace_dir;
std::string name;
bool usr_provided_outdir;
bool usr_provided_name;
};

} // namespace rr

#endif /* RR_UTIL_H_ */