aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-04 19:20:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-08 19:02:26 +0000
commit81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch)
tree311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
parent5fff09660e06a66bed6482da9c70df328e16bbb6 (diff)
parent145449b1e420787bb99721a429341fa6be3adfb6 (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp407
1 files changed, 324 insertions, 83 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
index c73f0df0aaf2..c76ae99057f2 100644
--- a/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectProcess.cpp
@@ -8,9 +8,12 @@
#include "CommandObjectProcess.h"
#include "CommandObjectTrace.h"
+#include "CommandObjectBreakpoint.h"
#include "CommandOptionsProcessLaunch.h"
#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
@@ -29,6 +32,8 @@
#include "lldb/Utility/Args.h"
#include "lldb/Utility/State.h"
+#include "llvm/ADT/ScopeExit.h"
+
#include <bitset>
using namespace lldb;
@@ -145,10 +150,10 @@ public:
Options *GetOptions() override { return &m_all_options; }
- const char *GetRepeatCommand(Args &current_command_args,
- uint32_t index) override {
+ llvm::Optional<std::string> GetRepeatCommand(Args &current_command_args,
+ uint32_t index) override {
// No repeat for "process launch"...
- return "";
+ return std::string("");
}
protected:
@@ -409,12 +414,6 @@ protected:
ModuleSP old_exec_module_sp = target->GetExecutableModule();
ArchSpec old_arch_spec = target->GetArchitecture();
- if (command.GetArgumentCount()) {
- result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
- m_cmd_name.c_str(), m_cmd_syntax.c_str());
- return false;
- }
-
StreamString stream;
ProcessSP process_sp;
const auto error = target->Attach(m_options.attach_info, &stream);
@@ -516,7 +515,7 @@ protected:
~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
- ExecutionContext *execution_context) override {
+ ExecutionContext *exe_ctx) override {
Status error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
@@ -526,7 +525,10 @@ protected:
"invalid value for ignore option: \"%s\", should be a number.",
option_arg.str().c_str());
break;
-
+ case 'b':
+ m_run_to_bkpt_args.AppendArgument(option_arg);
+ m_any_bkpts_specified = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -535,27 +537,25 @@ protected:
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_ignore = 0;
+ m_run_to_bkpt_args.Clear();
+ m_any_bkpts_specified = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::makeArrayRef(g_process_continue_options);
}
- uint32_t m_ignore;
+ uint32_t m_ignore = 0;
+ Args m_run_to_bkpt_args;
+ bool m_any_bkpts_specified = false;
};
+
bool DoExecute(Args &command, CommandReturnObject &result) override {
Process *process = m_exe_ctx.GetProcessPtr();
bool synchronous_execution = m_interpreter.GetSynchronous();
StateType state = process->GetState();
if (state == eStateStopped) {
- if (command.GetArgumentCount() != 0) {
- result.AppendErrorWithFormat(
- "The '%s' command does not take any arguments.\n",
- m_cmd_name.c_str());
- return false;
- }
-
if (m_options.m_ignore > 0) {
ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
if (sel_thread_sp) {
@@ -579,6 +579,130 @@ protected:
}
}
}
+
+ Target *target = m_exe_ctx.GetTargetPtr();
+ BreakpointIDList run_to_bkpt_ids;
+ // Don't pass an empty run_to_breakpoint list, as Verify will look for the
+ // default breakpoint.
+ if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
+ m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
+ BreakpointName::Permissions::disablePerm);
+ if (!result.Succeeded()) {
+ return false;
+ }
+ result.Clear();
+ if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {
+ result.AppendError("continue-to breakpoints did not specify any actual "
+ "breakpoints or locations");
+ return false;
+ }
+
+ // First figure out which breakpoints & locations were specified by the
+ // user:
+ size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();
+ std::vector<break_id_t> bkpts_disabled;
+ std::vector<BreakpointID> locs_disabled;
+ if (num_run_to_bkpt_ids != 0) {
+ // Go through the ID's specified, and separate the breakpoints from are
+ // the breakpoint.location specifications since the latter require
+ // special handling. We also figure out whether there's at least one
+ // specifier in the set that is enabled.
+ BreakpointList &bkpt_list = target->GetBreakpointList();
+ std::unordered_set<break_id_t> bkpts_seen;
+ std::unordered_set<break_id_t> bkpts_with_locs_seen;
+ BreakpointIDList with_locs;
+ bool any_enabled = false;
+
+ for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
+ BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
+ break_id_t bp_id = bkpt_id.GetBreakpointID();
+ break_id_t loc_id = bkpt_id.GetLocationID();
+ BreakpointSP bp_sp
+ = bkpt_list.FindBreakpointByID(bp_id);
+ // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
+ // don't need to do it again here.
+ if (bp_sp->IsEnabled()) {
+ if (loc_id == LLDB_INVALID_BREAK_ID) {
+ // A breakpoint (without location) was specified. Make sure that
+ // at least one of the locations is enabled.
+ size_t num_locations = bp_sp->GetNumLocations();
+ for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
+ BreakpointLocationSP loc_sp
+ = bp_sp->GetLocationAtIndex(loc_idx);
+ if (loc_sp->IsEnabled()) {
+ any_enabled = true;
+ break;
+ }
+ }
+ } else {
+ // A location was specified, check if it was enabled:
+ BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);
+ if (loc_sp->IsEnabled())
+ any_enabled = true;
+ }
+
+ // Then sort the bp & bp.loc entries for later use:
+ if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
+ bkpts_seen.insert(bkpt_id.GetBreakpointID());
+ else {
+ bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());
+ with_locs.AddBreakpointID(bkpt_id);
+ }
+ }
+ }
+ // Do all the error checking here so once we start disabling we don't
+ // have to back out half-way through.
+
+ // Make sure at least one of the specified breakpoints is enabled.
+ if (!any_enabled) {
+ result.AppendError("at least one of the continue-to breakpoints must "
+ "be enabled.");
+ return false;
+ }
+
+ // Also, if you specify BOTH a breakpoint and one of it's locations,
+ // we flag that as an error, since it won't do what you expect, the
+ // breakpoint directive will mean "run to all locations", which is not
+ // what the location directive means...
+ for (break_id_t bp_id : bkpts_with_locs_seen) {
+ if (bkpts_seen.count(bp_id)) {
+ result.AppendErrorWithFormatv("can't specify both a breakpoint and "
+ "one of its locations: {0}", bp_id);
+ }
+ }
+
+ // Now go through the breakpoints in the target, disabling all the ones
+ // that the user didn't mention:
+ for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
+ break_id_t bp_id = bp_sp->GetID();
+ // Handle the case where no locations were specified. Note we don't
+ // have to worry about the case where a breakpoint and one of its
+ // locations are both in the lists, we've already disallowed that.
+ if (!bkpts_with_locs_seen.count(bp_id)) {
+ if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {
+ bkpts_disabled.push_back(bp_id);
+ bp_sp->SetEnabled(false);
+ }
+ continue;
+ }
+ // Next, handle the case where a location was specified:
+ // Run through all the locations of this breakpoint and disable
+ // the ones that aren't on our "with locations" BreakpointID list:
+ size_t num_locations = bp_sp->GetNumLocations();
+ BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);
+ for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
+ BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
+ tmp_id.SetBreakpointLocationID(loc_idx);
+ size_t position = 0;
+ if (!with_locs.FindBreakpointID(tmp_id, &position)
+ && loc_sp->IsEnabled()) {
+ locs_disabled.push_back(tmp_id);
+ loc_sp->SetEnabled(false);
+ }
+ }
+ }
+ }
{ // Scope for thread list mutex:
std::lock_guard<std::recursive_mutex> guard(
@@ -597,10 +721,39 @@ protected:
StreamString stream;
Status error;
+ // For now we can only do -b with synchronous:
+ bool old_sync = GetDebugger().GetAsyncExecution();
+
+ if (run_to_bkpt_ids.GetSize() != 0) {
+ GetDebugger().SetAsyncExecution(false);
+ synchronous_execution = true;
+ }
if (synchronous_execution)
error = process->ResumeSynchronous(&stream);
else
error = process->Resume();
+
+ if (run_to_bkpt_ids.GetSize() != 0) {
+ GetDebugger().SetAsyncExecution(old_sync);
+ }
+
+ // Now re-enable the breakpoints we disabled:
+ BreakpointList &bkpt_list = target->GetBreakpointList();
+ for (break_id_t bp_id : bkpts_disabled) {
+ BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);
+ if (bp_sp)
+ bp_sp->SetEnabled(true);
+ }
+ for (const BreakpointID &bkpt_id : locs_disabled) {
+ BreakpointSP bp_sp
+ = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
+ if (bp_sp) {
+ BreakpointLocationSP loc_sp
+ = bp_sp->FindLocationByID(bkpt_id.GetLocationID());
+ if (loc_sp)
+ loc_sp->SetEnabled(true);
+ }
+ }
if (error.Success()) {
// There is a race condition where this thread will return up the call
@@ -777,7 +930,10 @@ public:
CommandObjectProcessConnect(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "process connect",
"Connect to a remote debug service.",
- "process connect <remote-url>", 0) {}
+ "process connect <remote-url>", 0) {
+ CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain};
+ m_arguments.push_back({connect_arg});
+ }
~CommandObjectProcessConnect() override = default;
@@ -902,7 +1058,10 @@ public:
"process load <filename> [<filename> ...]",
eCommandRequiresProcess | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused) {}
+ eCommandProcessMustBePaused) {
+ CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus};
+ m_arguments.push_back({file_arg});
+ }
~CommandObjectProcessLoad() override = default;
@@ -977,7 +1136,10 @@ public:
"returned by a previous call to \"process load\".",
"process unload <index>",
eCommandRequiresProcess | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
+ CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+ m_arguments.push_back({load_idx_arg});
+ }
~CommandObjectProcessUnload() override = default;
@@ -1125,18 +1287,13 @@ protected:
return false;
}
- if (command.GetArgumentCount() == 0) {
- bool clear_thread_plans = true;
- Status error(process->Halt(clear_thread_plans));
- if (error.Success()) {
- result.SetStatus(eReturnStatusSuccessFinishResult);
- } else {
- result.AppendErrorWithFormat("Failed to halt process: %s\n",
- error.AsCString());
- }
+ bool clear_thread_plans = true;
+ Status error(process->Halt(clear_thread_plans));
+ if (error.Success()) {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
- result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
- m_cmd_name.c_str(), m_cmd_syntax.c_str());
+ result.AppendErrorWithFormat("Failed to halt process: %s\n",
+ error.AsCString());
}
return result.Succeeded();
}
@@ -1164,17 +1321,12 @@ protected:
return false;
}
- if (command.GetArgumentCount() == 0) {
- Status error(process->Destroy(true));
- if (error.Success()) {
- result.SetStatus(eReturnStatusSuccessFinishResult);
- } else {
- result.AppendErrorWithFormat("Failed to kill process: %s\n",
- error.AsCString());
- }
+ Status error(process->Destroy(true));
+ if (error.Success()) {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
- result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
- m_cmd_name.c_str(), m_cmd_syntax.c_str());
+ result.AppendErrorWithFormat("Failed to kill process: %s\n",
+ error.AsCString());
}
return result.Succeeded();
}
@@ -1206,7 +1358,10 @@ public:
"appropriate file type.",
"process save-core [-s corefile-style -p plugin-name] FILE",
eCommandRequiresProcess | eCommandTryTargetAPILock |
- eCommandProcessMustBeLaunched) {}
+ eCommandProcessMustBeLaunched) {
+ CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain};
+ m_arguments.push_back({file_arg});
+ }
~CommandObjectProcessSaveCore() override = default;
@@ -1214,7 +1369,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() : m_requested_save_core_style(eSaveCoreUnspecified) {}
+ CommandOptions() = default;
~CommandOptions() override = default;
@@ -1250,7 +1405,7 @@ public:
}
// Instance variables to hold the values for command options.
- SaveCoreStyle m_requested_save_core_style;
+ SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified;
std::string m_requested_plugin_name;
};
@@ -1317,7 +1472,7 @@ public:
class CommandOptions : public Options {
public:
- CommandOptions() {}
+ CommandOptions() = default;
~CommandOptions() override = default;
@@ -1353,11 +1508,6 @@ protected:
Stream &strm = result.GetOutputStream();
result.SetStatus(eReturnStatusSuccessFinishNoResult);
- if (command.GetArgumentCount()) {
- result.AppendError("'process status' takes no arguments");
- return result.Succeeded();
- }
-
// No need to check "process" for validity as eCommandRequiresProcess
// ensures it is valid
Process *process = m_exe_ctx.GetProcessPtr();
@@ -1432,6 +1582,12 @@ public:
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
+ case 'c':
+ do_clear = true;
+ break;
+ case 'd':
+ dummy = true;
+ break;
case 's':
stop = std::string(option_arg);
break;
@@ -1441,6 +1597,9 @@ public:
case 'p':
pass = std::string(option_arg);
break;
+ case 't':
+ only_target_values = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -1451,6 +1610,9 @@ public:
stop.clear();
notify.clear();
pass.clear();
+ only_target_values = false;
+ do_clear = false;
+ dummy = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -1462,6 +1624,9 @@ public:
std::string stop;
std::string notify;
std::string pass;
+ bool only_target_values = false;
+ bool do_clear = false;
+ bool dummy = false;
};
CommandObjectProcessHandle(CommandInterpreter &interpreter)
@@ -1469,9 +1634,19 @@ public:
"Manage LLDB handling of OS signals for the "
"current target process. Defaults to showing "
"current policy.",
- nullptr, eCommandRequiresTarget) {
- SetHelpLong("\nIf no signals are specified, update them all. If no update "
- "option is specified, list the current values.");
+ nullptr) {
+ SetHelpLong("\nIf no signals are specified but one or more actions are, "
+ "and there is a live process, update them all. If no action "
+ "is specified, list the current values.\n"
+ "If you specify actions with no target (e.g. in an init file) "
+ "or in a target with no process "
+ "the values will get copied into subsequent targets, but "
+ "lldb won't be able to spell-check the options since it can't "
+ "know which signal set will later be in force."
+ "\nYou can see the signal modifications held by the target"
+ "by passing the -t option."
+ "\nYou can also clear the target modification for a signal"
+ "by passing the -c option");
CommandArgumentEntry arg;
CommandArgumentData signal_arg;
@@ -1554,15 +1729,13 @@ public:
protected:
bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
- Target *target_sp = &GetSelectedTarget();
+ Target &target = GetSelectedOrDummyTarget();
- ProcessSP process_sp = target_sp->GetProcessSP();
-
- if (!process_sp) {
- result.AppendError("No current process; cannot handle signals until you "
- "have a valid process.\n");
- return false;
- }
+ // Any signals that are being set should be added to the Target's
+ // DummySignals so they will get applied on rerun, etc.
+ // If we have a process, however, we can do a more accurate job of vetting
+ // the user's options.
+ ProcessSP process_sp = target.GetProcessSP();
int stop_action = -1; // -1 means leave the current setting alone
int pass_action = -1; // -1 means leave the current setting alone
@@ -1588,35 +1761,99 @@ protected:
"true or false.\n");
return false;
}
+
+ bool no_actions = (stop_action == -1 && pass_action == -1
+ && notify_action == -1);
+ if (m_options.only_target_values && !no_actions) {
+ result.AppendError("-t is for reporting, not setting, target values.");
+ return false;
+ }
size_t num_args = signal_args.GetArgumentCount();
- UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
+ UnixSignalsSP signals_sp;
+ if (process_sp)
+ signals_sp = process_sp->GetUnixSignals();
+
int num_signals_set = 0;
+ // If we were just asked to print the target values, do that here and
+ // return:
+ if (m_options.only_target_values) {
+ target.PrintDummySignals(result.GetOutputStream(), signal_args);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+ // This handles clearing values:
+ if (m_options.do_clear) {
+ target.ClearDummySignals(signal_args);
+ if (m_options.dummy)
+ GetDummyTarget().ClearDummySignals(signal_args);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+ // This rest handles setting values:
if (num_args > 0) {
for (const auto &arg : signal_args) {
- int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
- if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
- // Casting the actions as bools here should be okay, because
- // VerifyCommandOptionValue guarantees the value is either 0 or 1.
- if (stop_action != -1)
- signals_sp->SetShouldStop(signo, stop_action);
- if (pass_action != -1) {
- bool suppress = !pass_action;
- signals_sp->SetShouldSuppress(signo, suppress);
+ // Do the process first. If we have a process we can catch
+ // invalid signal names, which we do here.
+ if (signals_sp) {
+ int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
+ if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
+ // Casting the actions as bools here should be okay, because
+ // VerifyCommandOptionValue guarantees the value is either 0 or 1.
+ if (stop_action != -1)
+ signals_sp->SetShouldStop(signo, stop_action);
+ if (pass_action != -1) {
+ bool suppress = !pass_action;
+ signals_sp->SetShouldSuppress(signo, suppress);
+ }
+ if (notify_action != -1)
+ signals_sp->SetShouldNotify(signo, notify_action);
+ ++num_signals_set;
+ } else {
+ result.AppendErrorWithFormat("Invalid signal name '%s'\n",
+ arg.c_str());
+ continue;
}
- if (notify_action != -1)
- signals_sp->SetShouldNotify(signo, notify_action);
- ++num_signals_set;
} else {
- result.AppendErrorWithFormat("Invalid signal name '%s'\n",
- arg.c_str());
+ // If there's no process we can't check, so we just set them all.
+ // But since the map signal name -> signal number across all platforms
+ // is not 1-1, we can't sensibly set signal actions by number before
+ // we have a process. Check that here:
+ int32_t signo;
+ if (llvm::to_integer(arg.c_str(), signo)) {
+ result.AppendErrorWithFormat("Can't set signal handling by signal "
+ "number with no process");
+ return false;
+ }
+ num_signals_set = num_args;
}
+ auto set_lazy_bool = [] (int action) -> LazyBool {
+ LazyBool lazy;
+ if (action == -1)
+ lazy = eLazyBoolCalculate;
+ else if (action)
+ lazy = eLazyBoolYes;
+ else
+ lazy = eLazyBoolNo;
+ return lazy;
+ };
+
+ // If there were no actions, we're just listing, don't add the dummy:
+ if (!no_actions)
+ target.AddDummySignal(arg.ref(),
+ set_lazy_bool(pass_action),
+ set_lazy_bool(notify_action),
+ set_lazy_bool(stop_action));
}
} else {
// No signal specified, if any command options were specified, update ALL
- // signals.
- if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
+ // signals. But we can't do this without a process since we don't know
+ // all the possible signals that might be valid for this target.
+ if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
+ && process_sp) {
if (m_interpreter.Confirm(
"Do you really want to update all the signals?", false)) {
int32_t signo = signals_sp->GetFirstSignalNumber();
@@ -1635,11 +1872,15 @@ protected:
}
}
- PrintSignalInformation(result.GetOutputStream(), signal_args,
- num_signals_set, signals_sp);
+ if (signals_sp)
+ PrintSignalInformation(result.GetOutputStream(), signal_args,
+ num_signals_set, signals_sp);
+ else
+ target.PrintDummySignals(result.GetOutputStream(),
+ signal_args);
if (num_signals_set > 0)
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
else
result.SetStatus(eReturnStatusFailed);