summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBThread.h3
-rw-r--r--lldb/include/lldb/Target/SystemRuntime.h21
-rw-r--r--lldb/include/lldb/Target/Thread.h13
-rw-r--r--lldb/scripts/Python/interface/SBThread.i10
-rw-r--r--lldb/source/API/SBThread.cpp9
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp15
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h3
-rw-r--r--lldb/source/Target/Thread.cpp16
-rw-r--r--lldb/test/macosx/safe-to-func-call/Makefile28
-rw-r--r--lldb/test/macosx/safe-to-func-call/TestSafeFuncCalls.py81
-rw-r--r--lldb/test/macosx/safe-to-func-call/main.c30
15 files changed, 261 insertions, 0 deletions
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index f3b34728085..c71b55a52b1 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -210,6 +210,9 @@ public:
uint32_t
GetExtendedBacktraceOriginatingIndexID ();
+ bool
+ SafeToCallFunctions ();
+
protected:
friend class SBBreakpoint;
friend class SBBreakpointLocation;
diff --git a/lldb/include/lldb/Target/SystemRuntime.h b/lldb/include/lldb/Target/SystemRuntime.h
index 294d509ee64..7c6383491f6 100644
--- a/lldb/include/lldb/Target/SystemRuntime.h
+++ b/lldb/include/lldb/Target/SystemRuntime.h
@@ -309,6 +309,27 @@ public:
{
}
+ //------------------------------------------------------------------
+ /// Determine whether it is safe to run an expression on a given thread
+ ///
+ /// If a system must not run functions on a thread in some particular state,
+ /// this method gives a way for it to flag that the expression should not be
+ /// run.
+ ///
+ /// @param [in] thread_sp
+ /// The thread we want to run the expression on.
+ ///
+ /// @return
+ /// True will be returned if there are no known problems with running an
+ /// expression on this thread. False means that the inferior function
+ /// call should not be made on this thread.
+ //------------------------------------------------------------------
+ virtual bool
+ SafeToCallFunctionsOnThisThread (lldb::ThreadSP thread_sp)
+ {
+ return true;
+ }
+
protected:
//------------------------------------------------------------------
// Member variables.
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index a7b800a943e..dfd8390b710 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -592,6 +592,19 @@ public:
virtual lldb::addr_t
GetThreadLocalData (const lldb::ModuleSP module);
+ //------------------------------------------------------------------
+ /// Check whether this thread is safe to run functions
+ ///
+ /// The SystemRuntime may know of certain thread states (functions in
+ /// process of execution, for instance) which can make it unsafe for
+ /// functions to be called.
+ ///
+ /// @return
+ /// True if it is safe to call functions on this thread.
+ /// False if function calls should be avoided on this thread.
+ //------------------------------------------------------------------
+ virtual bool
+ SafeToCallFunctions ();
//------------------------------------------------------------------
// Thread Plan Providers:
diff --git a/lldb/scripts/Python/interface/SBThread.i b/lldb/scripts/Python/interface/SBThread.i
index ecf0475dec1..d1dd82a0cda 100644
--- a/lldb/scripts/Python/interface/SBThread.i
+++ b/lldb/scripts/Python/interface/SBThread.i
@@ -297,6 +297,16 @@ public:
uint32_t
GetExtendedBacktraceOriginatingIndexID();
+ %feature("autodoc","
+ Takes no arguments, returns a bool.
+ lldb may be able to detect that function calls should not be executed
+ on a given thread at a particular point in time. It is recommended that
+ this is checked before performing an inferior function call on a given
+ thread.
+ ") SafeToCallFunctions;
+ bool
+ SafeToCallFunctions ();
+
%pythoncode %{
class frames_access(object):
'''A helper object that will lazily hand out frames for a thread when supplied an index.'''
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 97bd6f4fed7..60731e85d0b 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -1437,3 +1437,12 @@ SBThread::GetExtendedBacktraceOriginatingIndexID ()
return thread_sp->GetExtendedBacktraceOriginatingIndexID();
return LLDB_INVALID_INDEX32;
}
+
+bool
+SBThread::SafeToCallFunctions ()
+{
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (thread_sp)
+ return thread_sp->SafeToCallFunctions();
+ return true;
+}
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
index 7d62548dbc5..64b2e229962 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
@@ -269,6 +269,14 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page
error.Clear();
+ if (thread.SafeToCallFunctions() == false)
+ {
+ if (log)
+ log->Printf ("Not safe to call functions on thread 0x%" PRIx64, thread.GetID());
+ error.SetErrorString ("Not safe to call functions on this thread.");
+ return return_value;
+ }
+
// Set up the arguments for a call to
// struct get_item_info_return_values
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
index ac39fef798b..51b797aa1ac 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
@@ -274,6 +274,14 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr
error.Clear();
+ if (thread.SafeToCallFunctions() == false)
+ {
+ if (log)
+ log->Printf ("Not safe to call functions on thread 0x%" PRIx64, thread.GetID());
+ error.SetErrorString ("Not safe to call functions on this thread.");
+ return return_value;
+ }
+
// Set up the arguments for a call to
// struct get_pending_items_return_values
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
index 403ebf1571f..cd15d475150 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
@@ -282,6 +282,14 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui
error.Clear();
+ if (thread.SafeToCallFunctions() == false)
+ {
+ if (log)
+ log->Printf ("Not safe to call functions on thread 0x%" PRIx64, thread.GetID());
+ error.SetErrorString ("Not safe to call functions on this thread.");
+ return return_value;
+ }
+
// Set up the arguments for a call to
// struct get_current_queues_return_values
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
index 40b61fe9981..46e76663c47 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
@@ -273,6 +273,14 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i
error.Clear();
+ if (thread.SafeToCallFunctions() == false)
+ {
+ if (log)
+ log->Printf ("Not safe to call functions on thread 0x%" PRIx64, thread.GetID());
+ error.SetErrorString ("Not safe to call functions on this thread.");
+ return return_value;
+ }
+
// Set up the arguments for a call to
// struct get_thread_item_info_return_values
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
index 7ff14fc5e09..f3f1fa31cd7 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
@@ -214,6 +214,21 @@ SystemRuntimeMacOSX::GetQueueKind (addr_t dispatch_queue_addr)
return kind;
}
+bool
+SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread (ThreadSP thread_sp)
+{
+ if (thread_sp && thread_sp->GetStackFrameCount() > 0 && thread_sp->GetFrameWithConcreteFrameIndex(0))
+ {
+ const SymbolContext sym_ctx (thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext (eSymbolContextSymbol));
+ static ConstString g_select_symbol ("__select");
+ if (sym_ctx.GetFunctionName() == g_select_symbol)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
lldb::queue_id_t
SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress (lldb::addr_t dispatch_qaddr)
{
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
index f7a4d2bfb16..30956fa3ece 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
@@ -108,6 +108,9 @@ public:
virtual lldb::QueueKind
GetQueueKind (lldb::addr_t dispatch_queue_addr);
+ virtual bool
+ SafeToCallFunctionsOnThisThread (lldb::ThreadSP thread_sp);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 4543dc03678..af5a9a45b25 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -26,6 +26,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -1953,6 +1954,21 @@ Thread::GetThreadLocalData (const ModuleSP module)
return LLDB_INVALID_ADDRESS;
}
+bool
+Thread::SafeToCallFunctions ()
+{
+ Process *process = GetProcess().get();
+ if (process)
+ {
+ SystemRuntime *runtime = process->GetSystemRuntime ();
+ if (runtime)
+ {
+ return runtime->SafeToCallFunctionsOnThisThread (shared_from_this());
+ }
+ }
+ return true;
+}
+
lldb::StackFrameSP
Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
{
diff --git a/lldb/test/macosx/safe-to-func-call/Makefile b/lldb/test/macosx/safe-to-func-call/Makefile
new file mode 100644
index 00000000000..d956512a279
--- /dev/null
+++ b/lldb/test/macosx/safe-to-func-call/Makefile
@@ -0,0 +1,28 @@
+CC ?= clang
+ifeq "$(ARCH)" ""
+ ARCH = x86_64
+endif
+
+ifeq "$(OS)" ""
+ OS = $(shell uname -s)
+endif
+
+CFLAGS ?= -g -O0
+CWD := $(shell pwd)
+
+LIB_PREFIX := lib
+
+ifeq "$(OS)" "Darwin"
+ CFLAGS += -arch $(ARCH)
+endif
+
+all: a.out
+
+a.out: main.o
+ $(CC) $(CFLAGS) -o a.out main.o
+
+main.o: main.c
+ $(CC) $(CFLAGS) -c main.c
+
+clean:
+ rm -rf *.o *~ *.dylib *.so a.out *.dSYM
diff --git a/lldb/test/macosx/safe-to-func-call/TestSafeFuncCalls.py b/lldb/test/macosx/safe-to-func-call/TestSafeFuncCalls.py
new file mode 100644
index 00000000000..be303d8697d
--- /dev/null
+++ b/lldb/test/macosx/safe-to-func-call/TestSafeFuncCalls.py
@@ -0,0 +1,81 @@
+"""Test function call thread safety."""
+
+import os, time
+import unittest2
+import lldb
+import lldbutil
+from lldbtest import *
+
+class TestSafeFuncCalls(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @python_api_test
+ @dsym_test
+ def test_with_dsym_and_python_api(self):
+ """Test function call thread safety."""
+ self.buildDsym()
+ self.function_call_safety_check()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @python_api_test
+ @dwarf_test
+ def test_with_dwarf_and_python_api(self):
+ """Test function call thread safety."""
+ self.buildDwarf()
+ self.function_call_safety_check()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line numbers that we will step to in main:
+ self.main_source = "main.c"
+
+
+
+ def check_number_of_threads(self, process):
+ self.assertTrue(process.GetNumThreads() == 2, "Check that the process has two threads when sitting at the stopper() breakpoint")
+
+ def safe_to_call_func_on_main_thread (self, main_thread):
+ self.assertTrue(main_thread.SafeToCallFunctions() == True, "It is safe to call functions on the main thread")
+
+ def safe_to_call_func_on_select_thread (self, select_thread):
+ self.assertTrue(select_thread.SafeToCallFunctions() == False, "It is not safe to call functions on the select thread")
+
+ def function_call_safety_check(self):
+ """Test function call safety checks"""
+ exe = os.path.join(os.getcwd(), "a.out")
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ self.main_source_spec = lldb.SBFileSpec (self.main_source)
+ break1 = target.BreakpointCreateByName ("stopper", 'a.out')
+ self.assertTrue(break1, VALID_BREAKPOINT)
+ process = target.LaunchSimple (None, None, self.get_process_working_directory())
+ self.assertTrue(process, PROCESS_IS_VALID)
+ threads = lldbutil.get_threads_stopped_at_breakpoint (process, break1)
+ if len(threads) != 1:
+ self.fail ("Failed to stop at breakpoint 1.")
+
+ self.check_number_of_threads(process)
+
+ main_thread = lldb.SBThread()
+ select_thread = lldb.SBThread()
+ for idx in range (0, process.GetNumThreads()):
+ t = process.GetThreadAtIndex (idx)
+ if t.GetName() == "main thread":
+ main_thread = t
+ if t.GetName() == "select thread":
+ select_thread = t
+
+ self.assertTrue(main_thread.IsValid() and select_thread.IsValid(), "Got both expected threads")
+
+ self.safe_to_call_func_on_main_thread (main_thread)
+ self.safe_to_call_func_on_select_thread (select_thread)
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/macosx/safe-to-func-call/main.c b/lldb/test/macosx/safe-to-func-call/main.c
new file mode 100644
index 00000000000..613384ff73b
--- /dev/null
+++ b/lldb/test/macosx/safe-to-func-call/main.c
@@ -0,0 +1,30 @@
+#include <sys/select.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void *
+select_thread (void *in)
+{
+ pthread_setname_np ("select thread");
+ fd_set fdset;
+ FD_SET (STDIN_FILENO, &fdset);
+ while (1)
+ select (2, &fdset, NULL, NULL, NULL);
+ return NULL;
+}
+
+void stopper ()
+{
+ while (1)
+ sleep(1); // break here
+}
+
+int main ()
+{
+ pthread_setname_np ("main thread");
+ pthread_t other_thread;
+ pthread_create (&other_thread, NULL, select_thread, NULL);
+ sleep (1);
+ stopper();
+}
OpenPOWER on IntegriCloud