forked from OSchip/llvm-project
Fixed a case where we might be able to acquire a mutex with a try lock and
not release it by making sure a mutex locker object is appropriately used. llvm-svn: 112996
This commit is contained in:
parent
78395e4b8a
commit
54512bd6c9
|
@ -78,8 +78,7 @@ Mutex::Locker::Locker (pthread_mutex_t *mutex_ptr) :
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
Mutex::Locker::~Locker ()
|
Mutex::Locker::~Locker ()
|
||||||
{
|
{
|
||||||
if (m_mutex_ptr)
|
Reset();
|
||||||
Mutex::Unlock (m_mutex_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
@ -89,6 +88,10 @@ Mutex::Locker::~Locker ()
|
||||||
void
|
void
|
||||||
Mutex::Locker::Reset (pthread_mutex_t *mutex_ptr)
|
Mutex::Locker::Reset (pthread_mutex_t *mutex_ptr)
|
||||||
{
|
{
|
||||||
|
// We already have this mutex locked or both are NULL...
|
||||||
|
if (m_mutex_ptr == mutex_ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
if (m_mutex_ptr)
|
if (m_mutex_ptr)
|
||||||
Mutex::Unlock (m_mutex_ptr);
|
Mutex::Unlock (m_mutex_ptr);
|
||||||
|
|
||||||
|
@ -100,9 +103,12 @@ Mutex::Locker::Reset (pthread_mutex_t *mutex_ptr)
|
||||||
bool
|
bool
|
||||||
Mutex::Locker::TryLock (pthread_mutex_t *mutex_ptr)
|
Mutex::Locker::TryLock (pthread_mutex_t *mutex_ptr)
|
||||||
{
|
{
|
||||||
if (m_mutex_ptr)
|
// We already have this mutex locked!
|
||||||
Mutex::Unlock (m_mutex_ptr);
|
if (m_mutex_ptr == mutex_ptr)
|
||||||
m_mutex_ptr = NULL;
|
return true;
|
||||||
|
|
||||||
|
Reset ();
|
||||||
|
|
||||||
if (mutex_ptr)
|
if (mutex_ptr)
|
||||||
{
|
{
|
||||||
if (Mutex::TryLock (mutex_ptr) == 0)
|
if (Mutex::TryLock (mutex_ptr) == 0)
|
||||||
|
|
|
@ -124,7 +124,7 @@ GDBRemoteCommunication::SendPacketAndWaitForResponse
|
||||||
timeout_time = TimeValue::Now();
|
timeout_time = TimeValue::Now();
|
||||||
timeout_time.OffsetWithSeconds (timeout_seconds);
|
timeout_time.OffsetWithSeconds (timeout_seconds);
|
||||||
|
|
||||||
if (locker.TryLock (m_sequence_mutex.GetMutex()))
|
if (GetSequenceMutex (locker))
|
||||||
{
|
{
|
||||||
if (SendPacketNoLock (payload, strlen(payload)))
|
if (SendPacketNoLock (payload, strlen(payload)))
|
||||||
return WaitForPacketNoLock (response, &timeout_time);
|
return WaitForPacketNoLock (response, &timeout_time);
|
||||||
|
@ -139,7 +139,7 @@ GDBRemoteCommunication::SendPacketAndWaitForResponse
|
||||||
m_async_packet_predicate.SetValue (true, eBroadcastNever);
|
m_async_packet_predicate.SetValue (true, eBroadcastNever);
|
||||||
|
|
||||||
bool timed_out = false;
|
bool timed_out = false;
|
||||||
if (SendInterrupt(1, &timed_out))
|
if (SendInterrupt(locker, 1, &timed_out))
|
||||||
{
|
{
|
||||||
if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
|
if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
|
||||||
{
|
{
|
||||||
|
@ -396,14 +396,25 @@ GDBRemoteCommunication::SendAsyncSignal (int signo)
|
||||||
{
|
{
|
||||||
m_async_signal = signo;
|
m_async_signal = signo;
|
||||||
bool timed_out = false;
|
bool timed_out = false;
|
||||||
if (SendInterrupt(1, &timed_out))
|
Mutex::Locker locker;
|
||||||
|
if (SendInterrupt (locker, 1, &timed_out))
|
||||||
return true;
|
return true;
|
||||||
m_async_signal = -1;
|
m_async_signal = -1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function takes a mutex locker as a parameter in case the GetSequenceMutex
|
||||||
|
// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
|
||||||
|
// (the expected result), then it will send the halt packet. If it does succeed
|
||||||
|
// then the caller that requested the interrupt will want to keep the sequence
|
||||||
|
// locked down so that no one else can send packets while the caller has control.
|
||||||
|
// This function usually gets called when we are running and need to stop the
|
||||||
|
// target. It can also be used when we are running and and we need to do something
|
||||||
|
// else (like read/write memory), so we need to interrupt the running process
|
||||||
|
// (gdb remote protocol requires this), and do what we need to do, then resume.
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GDBRemoteCommunication::SendInterrupt (uint32_t seconds_to_wait_for_stop, bool *timed_out)
|
GDBRemoteCommunication::SendInterrupt (Mutex::Locker& locker, uint32_t seconds_to_wait_for_stop, bool *timed_out)
|
||||||
{
|
{
|
||||||
if (timed_out)
|
if (timed_out)
|
||||||
*timed_out = false;
|
*timed_out = false;
|
||||||
|
@ -411,7 +422,7 @@ GDBRemoteCommunication::SendInterrupt (uint32_t seconds_to_wait_for_stop, bool *
|
||||||
if (IsConnected() && IsRunning())
|
if (IsConnected() && IsRunning())
|
||||||
{
|
{
|
||||||
// Only send an interrupt if our debugserver is running...
|
// Only send an interrupt if our debugserver is running...
|
||||||
if (m_sequence_mutex.TryLock() != 0)
|
if (GetSequenceMutex (locker) == false)
|
||||||
{
|
{
|
||||||
// Someone has the mutex locked waiting for a response or for the
|
// Someone has the mutex locked waiting for a response or for the
|
||||||
// inferior to stop, so send the interrupt on the down low...
|
// inferior to stop, so send the interrupt on the down low...
|
||||||
|
|
|
@ -99,7 +99,9 @@ public:
|
||||||
SendAsyncSignal (int signo);
|
SendAsyncSignal (int signo);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SendInterrupt (uint32_t seconds_to_wait_for_stop, bool *timed_out = NULL);
|
SendInterrupt (lldb_private::Mutex::Locker &locker,
|
||||||
|
uint32_t seconds_to_wait_for_stop,
|
||||||
|
bool *timed_out = NULL);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetSequenceMutex(lldb_private::Mutex::Locker& locker);
|
GetSequenceMutex(lldb_private::Mutex::Locker& locker);
|
||||||
|
|
|
@ -1117,7 +1117,8 @@ ProcessGDBRemote::DoHalt ()
|
||||||
if (m_gdb_comm.IsRunning())
|
if (m_gdb_comm.IsRunning())
|
||||||
{
|
{
|
||||||
bool timed_out = false;
|
bool timed_out = false;
|
||||||
if (!m_gdb_comm.SendInterrupt (2, &timed_out))
|
Mutex::Locker locker;
|
||||||
|
if (!m_gdb_comm.SendInterrupt (locker, 2, &timed_out))
|
||||||
{
|
{
|
||||||
if (timed_out)
|
if (timed_out)
|
||||||
error.SetErrorString("timed out sending interrupt packet");
|
error.SetErrorString("timed out sending interrupt packet");
|
||||||
|
@ -1150,7 +1151,8 @@ ProcessGDBRemote::DoDestroy ()
|
||||||
log->Printf ("ProcessGDBRemote::DoDestroy()");
|
log->Printf ("ProcessGDBRemote::DoDestroy()");
|
||||||
|
|
||||||
// Interrupt if our inferior is running...
|
// Interrupt if our inferior is running...
|
||||||
m_gdb_comm.SendInterrupt (1);
|
Mutex::Locker locker;
|
||||||
|
m_gdb_comm.SendInterrupt (locker, 1);
|
||||||
DisableAllBreakpointSites ();
|
DisableAllBreakpointSites ();
|
||||||
SetExitStatus(-1, "process killed");
|
SetExitStatus(-1, "process killed");
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,14 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "debugserver" */;
|
buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "debugserver" */;
|
||||||
compatibilityVersion = "Xcode 3.1";
|
compatibilityVersion = "Xcode 3.1";
|
||||||
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 1;
|
hasScannedForEncodings = 1;
|
||||||
|
knownRegions = (
|
||||||
|
English,
|
||||||
|
Japanese,
|
||||||
|
French,
|
||||||
|
German,
|
||||||
|
);
|
||||||
mainGroup = 08FB7794FE84155DC02AAC07 /* dbgnub */;
|
mainGroup = 08FB7794FE84155DC02AAC07 /* dbgnub */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
|
|
Loading…
Reference in New Issue