Recommitting r180831 with trivial fix - remember to return errors if you compute.

llvm-svn: 180898
This commit is contained in:
Jim Ingham
2013-05-02 00:27:30 +00:00
parent ae4a5567e1
commit acff895015
14 changed files with 221 additions and 30 deletions

View File

@@ -204,6 +204,9 @@ public:
lldb::SBError
Detach ();
lldb::SBError
Detach (bool keep_stopped);
lldb::SBError
Signal (int signal);

View File

@@ -91,6 +91,12 @@ public:
void
SetStopOnSharedLibraryEvents (bool stop);
bool
GetDetachKeepsStopped () const;
void
SetDetachKeepsStopped (bool keep_stopped);
};
typedef std::shared_ptr<ProcessProperties> ProcessPropertiesSP;
@@ -1943,11 +1949,14 @@ public:
/// This function is not meant to be overridden by Process
/// subclasses.
///
/// @param[in] keep_stopped
/// If true, don't resume the process on detach.
///
/// @return
/// Returns an error object.
//------------------------------------------------------------------
Error
Detach ();
Detach (bool keep_stopped);
//------------------------------------------------------------------
/// Kills the process and shuts down all threads that were spawned
@@ -2334,7 +2343,7 @@ public:
/// false otherwise.
//------------------------------------------------------------------
virtual Error
DoDetach ()
DoDetach (bool keep_stopped)
{
Error error;
error.SetErrorStringWithFormat("error: %s does not support detaching from processes", GetShortPluginName());

View File

@@ -785,13 +785,21 @@ SBProcess::Kill ()
SBError
SBProcess::Detach ()
{
// FIXME: This should come from a process default.
bool keep_stopped = false;
return Detach (keep_stopped);
}
SBError
SBProcess::Detach (bool keep_stopped)
{
SBError sb_error;
ProcessSP process_sp(GetSP());
if (process_sp)
{
Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
sb_error.SetError (process_sp->Detach());
sb_error.SetError (process_sp->Detach(keep_stopped));
}
else
sb_error.SetErrorString ("SBProcess is invalid");

View File

@@ -75,7 +75,8 @@ protected:
{
if (process->GetShouldDetach())
{
Error detach_error (process->Detach());
bool keep_stopped = false;
Error detach_error (process->Detach(keep_stopped));
if (detach_error.Success())
{
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -903,6 +904,68 @@ CommandObjectProcessContinue::CommandOptions::g_option_table[] =
class CommandObjectProcessDetach : public CommandObjectParsed
{
public:
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options (interpreter)
{
OptionParsingStarting ();
}
~CommandOptions ()
{
}
Error
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
const int short_option = m_getopt_table[option_idx].val;
switch (short_option)
{
case 's':
bool tmp_result;
bool success;
tmp_result = Args::StringToBoolean(option_arg, false, &success);
if (!success)
error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg);
else
{
if (tmp_result)
m_keep_stopped = eLazyBoolYes;
else
m_keep_stopped = eLazyBoolNo;
}
break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
break;
}
return error;
}
void
OptionParsingStarting ()
{
m_keep_stopped = eLazyBoolCalculate;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
// Instance variables to hold the values for command options.
LazyBool m_keep_stopped;
};
CommandObjectProcessDetach (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
@@ -911,7 +974,8 @@ public:
"process detach",
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched)
eFlagProcessMustBeLaunched),
m_options(interpreter)
{
}
@@ -919,13 +983,35 @@ public:
{
}
Options *
GetOptions ()
{
return &m_options;
}
protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_exe_ctx.GetProcessPtr();
result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
Error error (process->Detach());
// FIXME: This will be a Command Option:
bool keep_stopped;
if (m_options.m_keep_stopped == eLazyBoolCalculate)
{
// Check the process default:
if (process->GetDetachKeepsStopped())
keep_stopped = true;
else
keep_stopped = false;
}
else if (m_options.m_keep_stopped == eLazyBoolYes)
keep_stopped = true;
else
keep_stopped = false;
Error error (process->Detach(keep_stopped));
if (error.Success())
{
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -938,6 +1024,15 @@ protected:
}
return result.Succeeded();
}
CommandOptions m_options;
};
OptionDefinition
CommandObjectProcessDetach::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "keep-stopped", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
//-------------------------------------------------------------------------

View File

@@ -295,7 +295,6 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
else
{
StateType state = process->GetState();
switch (state)
{
case eStateInvalid:

View File

@@ -507,12 +507,12 @@ ProcessKDP::DoHalt (bool &caused_stop)
}
Error
ProcessKDP::DoDetach()
ProcessKDP::DoDetach(bool keep_stopped)
{
Error error;
Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
if (log)
log->Printf ("ProcessKDP::DoDetach()");
log->Printf ("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
if (m_comm.IsRunning())
{
@@ -525,7 +525,8 @@ ProcessKDP::DoDetach()
m_thread_list.DiscardThreadPlans();
if (m_comm.IsConnected())
// If we are going to keep the target stopped, then don't send the disconnect message.
if (!keep_stopped && m_comm.IsConnected())
{
m_comm.SendRequestDisconnect();
@@ -554,7 +555,8 @@ Error
ProcessKDP::DoDestroy ()
{
// For KDP there really is no difference between destroy and detach
return DoDetach();
bool keep_stopped = false;
return DoDetach(keep_stopped);
}
//------------------------------------------------------------------

View File

@@ -135,7 +135,7 @@ public:
DoHalt (bool &caused_stop);
virtual lldb_private::Error
DoDetach ();
DoDetach (bool keep_stopped);
virtual lldb_private::Error
DoSignal (int signal);

View File

@@ -283,9 +283,16 @@ ProcessPOSIX::DoHalt(bool &caused_stop)
}
Error
ProcessPOSIX::DoDetach()
ProcessPOSIX::DoDetach(bool keep_stopped)
{
Error error;
if (keep_stopped)
{
// FIXME: If you want to implement keep_stopped on Linux,
// this would be the place to do it.
error.SetErrorString("Detaching with keep_stopped true is not currently supported on Linux.");
return error;
}
error = m_monitor->Detach();
if (error.Success())

View File

@@ -65,7 +65,7 @@ public:
DoHalt(bool &caused_stop);
virtual lldb_private::Error
DoDetach();
DoDetach(bool keep_stopped);
virtual lldb_private::Error
DoSignal(int signal);

View File

@@ -52,6 +52,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
m_supports_memory_region_info (eLazyBoolCalculate),
m_supports_watchpoint_support_info (eLazyBoolCalculate),
m_supports_detach_stay_stopped (eLazyBoolCalculate),
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
@@ -1396,10 +1397,48 @@ GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
return false;
}
bool
GDBRemoteCommunicationClient::Detach ()
Error
GDBRemoteCommunicationClient::Detach (bool keep_stopped)
{
return SendPacket ("D", 1) > 0;
Error error;
if (keep_stopped)
{
if (m_supports_detach_stay_stopped == eLazyBoolCalculate)
{
char packet[64];
const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
assert (packet_len < sizeof(packet));
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
{
m_supports_detach_stay_stopped = eLazyBoolYes;
}
else
{
m_supports_detach_stay_stopped = eLazyBoolNo;
}
}
if (m_supports_detach_stay_stopped == eLazyBoolNo)
{
error.SetErrorString("Stays stopped not supported by this target.");
return error;
}
else
{
size_t num_sent = SendPacket ("D1", 2);
if (num_sent == 0)
error.SetErrorString ("Sending extended disconnect packet failed.");
}
}
else
{
size_t num_sent = SendPacket ("D", 1);
if (num_sent == 0)
error.SetErrorString ("Sending disconnect packet failed.");
}
return error;
}
Error

View File

@@ -199,8 +199,8 @@ public:
bool
DeallocateMemory (lldb::addr_t addr);
bool
Detach ();
lldb_private::Error
Detach (bool keep_stopped);
lldb_private::Error
GetMemoryRegionInfo (lldb::addr_t addr,
@@ -381,6 +381,7 @@ protected:
lldb_private::LazyBool m_supports_alloc_dealloc_memory;
lldb_private::LazyBool m_supports_memory_region_info;
lldb_private::LazyBool m_supports_watchpoint_support_info;
lldb_private::LazyBool m_supports_detach_stay_stopped;
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;

View File

@@ -1696,25 +1696,29 @@ ProcessGDBRemote::DoHalt (bool &caused_stop)
}
Error
ProcessGDBRemote::DoDetach()
ProcessGDBRemote::DoDetach(bool keep_stopped)
{
Error error;
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
log->Printf ("ProcessGDBRemote::DoDetach()");
log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
DisableAllBreakpointSites ();
m_thread_list.DiscardThreadPlans();
bool success = m_gdb_comm.Detach ();
error = m_gdb_comm.Detach (keep_stopped);
if (log)
{
if (success)
if (error.Success())
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
else
log->PutCString ("ProcessGDBRemote::DoDetach() detach packet send failed");
log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
}
if (!error.Success())
return error;
// Sleep for one second to let the process get all detached...
StopAsyncThread ();

View File

@@ -141,7 +141,7 @@ public:
DoHalt (bool &caused_stop);
virtual lldb_private::Error
DoDetach ();
DoDetach (bool keep_stopped);
virtual bool
DetachRequiresHalt() { return true; }

View File

@@ -101,6 +101,7 @@ g_properties[] =
{ "unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, errors in expression evaluation will unwind the stack back to the state before the call." },
{ "python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." },
{ "stop-on-sharedlibrary-events" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, stop when a shared library is loaded or unloaded." },
{ "detach-keeps-stopped" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, detach will attempt to keep the process stopped." },
{ NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
};
@@ -110,7 +111,8 @@ enum {
ePropertyIgnoreBreakpointsInExpressions,
ePropertyUnwindOnErrorInExpressions,
ePropertyPythonOSPluginPath,
ePropertyStopOnSharedLibraryEvents
ePropertyStopOnSharedLibraryEvents,
ePropertyDetachKeepsStopped
};
ProcessProperties::ProcessProperties (bool is_global) :
@@ -213,6 +215,20 @@ ProcessProperties::SetStopOnSharedLibraryEvents (bool stop)
m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
}
bool
ProcessProperties::GetDetachKeepsStopped () const
{
const uint32_t idx = ePropertyDetachKeepsStopped;
return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value != 0);
}
void
ProcessProperties::SetDetachKeepsStopped (bool stop)
{
const uint32_t idx = ePropertyDetachKeepsStopped;
m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, stop);
}
void
ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
{
@@ -1096,7 +1112,11 @@ Process::Finalize()
case eStateCrashed:
case eStateSuspended:
if (GetShouldDetach())
Detach();
{
// FIXME: This will have to be a process setting:
bool keep_stopped = false;
Detach(keep_stopped);
}
else
Destroy();
break;
@@ -3437,7 +3457,7 @@ Process::HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp)
}
Error
Process::Detach ()
Process::Detach (bool keep_stopped)
{
EventSP exit_event_sp;
Error error;
@@ -3464,12 +3484,16 @@ Process::Detach ()
}
}
error = DoDetach();
error = DoDetach(keep_stopped);
if (error.Success())
{
DidDetach();
StopPrivateStateThread();
}
else
{
return error;
}
}
m_destroy_in_process = false;