[Lldb-commits] [lldb] r242391 - Revert "[NativeProcessLinux] Integrate MainLoop"

Pavel Labath labath at google.com
Thu Jul 16 01:45:04 PDT 2015


Author: labath
Date: Thu Jul 16 03:45:03 2015
New Revision: 242391

URL: http://llvm.org/viewvc/llvm-project?rev=242391&view=rev
Log:
Revert "[NativeProcessLinux] Integrate MainLoop"

This seems to be causing major slowdows on the android buildbot. Reverting while I investigate.

Modified:
    lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
    lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

Modified: lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h Thu Jul 16 03:45:03 2015
@@ -16,7 +16,6 @@
 #include "lldb/lldb-types.h"
 #include "lldb/Core/Error.h"
 #include "lldb/Host/Mutex.h"
-#include "lldb/Host/MainLoop.h"
 #include "llvm/ADT/StringRef.h"
 
 #include "NativeBreakpointList.h"
@@ -285,6 +284,10 @@ namespace lldb_private
         bool
         UnregisterNativeDelegate (NativeDelegate &native_delegate);
 
+        // Called before termination of NativeProcessProtocol's instance.
+        virtual void
+        Terminate ();
+
         virtual Error
         GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) = 0;
 
@@ -304,11 +307,6 @@ namespace lldb_private
         ///     inferior.  Must outlive the NativeProcessProtocol
         ///     instance.
         ///
-        /// @param[in] mainloop
-        ///     The mainloop instance with which the process can register
-        ///     callbacks. Must outlive the NativeProcessProtocol
-        ///     instance.
-        ///
         /// @param[out] process_sp
         ///     On successful return from the method, this parameter
         ///     contains the shared pointer to the
@@ -322,7 +320,6 @@ namespace lldb_private
         static Error
         Launch (ProcessLaunchInfo &launch_info,
                 NativeDelegate &native_delegate,
-                MainLoop &mainloop,
                 NativeProcessProtocolSP &process_sp);
 
         //------------------------------------------------------------------
@@ -338,11 +335,6 @@ namespace lldb_private
         ///     inferior.  Must outlive the NativeProcessProtocol
         ///     instance.
         ///
-        /// @param[in] mainloop
-        ///     The mainloop instance with which the process can register
-        ///     callbacks. Must outlive the NativeProcessProtocol
-        ///     instance.
-        ///
         /// @param[out] process_sp
         ///     On successful return from the method, this parameter
         ///     contains the shared pointer to the
@@ -356,7 +348,6 @@ namespace lldb_private
         static Error
         Attach (lldb::pid_t pid,
                 NativeDelegate &native_delegate,
-                MainLoop &mainloop,
                 NativeProcessProtocolSP &process_sp);
 
     protected:

Modified: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp (original)
+++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp Thu Jul 16 03:45:03 2015
@@ -436,6 +436,12 @@ NativeProcessProtocol::DoStopIDBumped (u
     // Default implementation does nothing.
 }
 
+void
+NativeProcessProtocol::Terminate ()
+{
+    // Default implementation does nothing.
+}
+
 #ifndef __linux__
 // These need to be implemented to support lldb-gdb-server on a given platform. Stubs are
 // provided to make the rest of the code link on non-supported platforms.
@@ -443,7 +449,6 @@ NativeProcessProtocol::DoStopIDBumped (u
 Error
 NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
         NativeDelegate &native_delegate,
-        MainLoop &mainloop,
         NativeProcessProtocolSP &process_sp)
 {
     llvm_unreachable("Platform has no NativeProcessProtocol support");
@@ -452,7 +457,6 @@ NativeProcessProtocol::Launch (ProcessLa
 Error
 NativeProcessProtocol::Attach (lldb::pid_t pid,
         NativeDelegate &native_delegate,
-        MainLoop &mainloop,
         NativeProcessProtocolSP &process_sp)
 {
     llvm_unreachable("Platform has no NativeProcessProtocol support");

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Thu Jul 16 03:45:03 2015
@@ -11,6 +11,7 @@
 
 // C Includes
 #include <errno.h>
+#include <semaphore.h>
 #include <string.h>
 #include <stdint.h>
 #include <unistd.h>
@@ -212,8 +213,157 @@ namespace
         }
     }
 
-    static constexpr unsigned k_ptrace_word_size = sizeof(void*);
-    static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size");
+    //------------------------------------------------------------------------------
+    // Static implementations of NativeProcessLinux::ReadMemory and
+    // NativeProcessLinux::WriteMemory.  This enables mutual recursion between these
+    // functions without needed to go thru the thread funnel.
+
+    Error
+    DoReadMemory(
+        lldb::pid_t pid,
+        lldb::addr_t vm_addr,
+        void *buf,
+        size_t size,
+        size_t &bytes_read)
+    {
+        // ptrace word size is determined by the host, not the child
+        static const unsigned word_size = sizeof(void*);
+        unsigned char *dst = static_cast<unsigned char*>(buf);
+        size_t remainder;
+        long data;
+
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+        if (log)
+            ProcessPOSIXLog::IncNestLevel();
+        if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
+            log->Printf ("NativeProcessLinux::%s(%" PRIu64 ", %d, %p, %p, %zd, _)", __FUNCTION__,
+                    pid, word_size, (void*)vm_addr, buf, size);
+
+        assert(sizeof(data) >= word_size);
+        for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
+        {
+            Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, &data);
+            if (error.Fail())
+            {
+                if (log)
+                    ProcessPOSIXLog::DecNestLevel();
+                return error;
+            }
+
+            remainder = size - bytes_read;
+            remainder = remainder > word_size ? word_size : remainder;
+
+            // Copy the data into our buffer
+            for (unsigned i = 0; i < remainder; ++i)
+                dst[i] = ((data >> i*8) & 0xFF);
+
+            if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+                    (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+                            (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+                                    size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
+            {
+                uintptr_t print_dst = 0;
+                // Format bytes from data by moving into print_dst for log output
+                for (unsigned i = 0; i < remainder; ++i)
+                    print_dst |= (((data >> i*8) & 0xFF) << i*8);
+                log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                        (void*)vm_addr, print_dst, (unsigned long)data);
+            }
+            vm_addr += word_size;
+            dst += word_size;
+        }
+
+        if (log)
+            ProcessPOSIXLog::DecNestLevel();
+        return Error();
+    }
+
+    Error
+    DoWriteMemory(
+        lldb::pid_t pid,
+        lldb::addr_t vm_addr,
+        const void *buf,
+        size_t size,
+        size_t &bytes_written)
+    {
+        // ptrace word size is determined by the host, not the child
+        static const unsigned word_size = sizeof(void*);
+        const unsigned char *src = static_cast<const unsigned char*>(buf);
+        size_t remainder;
+        Error error;
+
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
+        if (log)
+            ProcessPOSIXLog::IncNestLevel();
+        if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
+            log->Printf ("NativeProcessLinux::%s(%" PRIu64 ", %u, %p, %p, %" PRIu64 ")", __FUNCTION__,
+                    pid, word_size, (void*)vm_addr, buf, size);
+
+        for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
+        {
+            remainder = size - bytes_written;
+            remainder = remainder > word_size ? word_size : remainder;
+
+            if (remainder == word_size)
+            {
+                unsigned long data = 0;
+                assert(sizeof(data) >= word_size);
+                for (unsigned i = 0; i < word_size; ++i)
+                    data |= (unsigned long)src[i] << i*8;
+
+                if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+                        (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+                                (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+                                        size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
+                    log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                            (void*)vm_addr, *(const unsigned long*)src, data);
+
+                error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data);
+                if (error.Fail())
+                {
+                    if (log)
+                        ProcessPOSIXLog::DecNestLevel();
+                    return error;
+                }
+            }
+            else
+            {
+                unsigned char buff[8];
+                size_t bytes_read;
+                error = DoReadMemory(pid, vm_addr, buff, word_size, bytes_read);
+                if (error.Fail())
+                {
+                    if (log)
+                        ProcessPOSIXLog::DecNestLevel();
+                    return error;
+                }
+
+                memcpy(buff, src, remainder);
+
+                size_t bytes_written_rec;
+                error = DoWriteMemory(pid, vm_addr, buff, word_size, bytes_written_rec);
+                if (error.Fail())
+                {
+                    if (log)
+                        ProcessPOSIXLog::DecNestLevel();
+                    return error;
+                }
+
+                if (log && ProcessPOSIXLog::AtTopNestLevel() &&
+                        (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
+                                (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
+                                        size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
+                    log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
+                            (void*)vm_addr, *(const unsigned long*)src, *(unsigned long*)buff);
+            }
+
+            vm_addr += word_size;
+            src += word_size;
+        }
+        if (log)
+            ProcessPOSIXLog::DecNestLevel();
+        return error;
+    }
 } // end of anonymous namespace
 
 // Simple helper function to ensure flags are enabled on the given file
@@ -239,6 +389,406 @@ EnsureFDFlags(int fd, int flags)
     return error;
 }
 
+// This class encapsulates the privileged thread which performs all ptrace and wait operations on
+// the inferior. The thread consists of a main loop which waits for events and processes them
+//   - SIGCHLD (delivered over a signalfd file descriptor): These signals notify us of events in
+//     the inferior process. Upon receiving this signal we do a waitpid to get more information
+//     and dispatch to NativeProcessLinux::MonitorCallback.
+//   - requests for ptrace operations: These initiated via the DoOperation method, which funnels
+//     them to the Monitor thread via m_operation member. The Monitor thread is signaled over a
+//     pipe, and the completion of the operation is signalled over the semaphore.
+//   - thread exit event: this is signaled from the Monitor destructor by closing the write end
+//     of the command pipe.
+class NativeProcessLinux::Monitor
+{
+private:
+    // The initial monitor operation (launch or attach). It returns a inferior process id.
+    std::unique_ptr<InitialOperation> m_initial_operation_up;
+
+    ::pid_t                           m_child_pid = -1;
+    NativeProcessLinux              * m_native_process;
+
+    enum { READ, WRITE };
+    int        m_pipefd[2] = {-1, -1};
+    int        m_signal_fd = -1;
+    HostThread m_thread;
+
+    // current operation which must be executed on the priviliged thread
+    Mutex            m_operation_mutex;
+    const Operation *m_operation = nullptr;
+    sem_t            m_operation_sem;
+    Error            m_operation_error;
+
+    unsigned   m_operation_nesting_level = 0;
+
+    static constexpr char operation_command   = 'o';
+    static constexpr char begin_block_command = '{';
+    static constexpr char end_block_command   = '}';
+
+    void
+    HandleSignals();
+
+    void
+    HandleWait();
+
+    // Returns true if the thread should exit.
+    bool
+    HandleCommands();
+
+    void
+    MainLoop();
+
+    static void *
+    RunMonitor(void *arg);
+
+    Error
+    WaitForAck();
+
+    void
+    BeginOperationBlock()
+    {
+        write(m_pipefd[WRITE], &begin_block_command, sizeof operation_command);
+        WaitForAck();
+    }
+
+    void
+    EndOperationBlock()
+    {
+        write(m_pipefd[WRITE], &end_block_command, sizeof operation_command);
+        WaitForAck();
+    }
+
+public:
+    Monitor(const InitialOperation &initial_operation,
+            NativeProcessLinux *native_process)
+        : m_initial_operation_up(new InitialOperation(initial_operation)),
+          m_native_process(native_process)
+    {
+        sem_init(&m_operation_sem, 0, 0);
+    }
+
+    ~Monitor();
+
+    Error
+    Initialize();
+
+    void
+    Terminate();
+
+    Error
+    DoOperation(const Operation &op);
+
+    class ScopedOperationLock {
+        Monitor &m_monitor;
+
+    public:
+        ScopedOperationLock(Monitor &monitor)
+            : m_monitor(monitor)
+        { m_monitor.BeginOperationBlock(); }
+
+        ~ScopedOperationLock()
+        { m_monitor.EndOperationBlock(); }
+    };
+};
+constexpr char NativeProcessLinux::Monitor::operation_command;
+constexpr char NativeProcessLinux::Monitor::begin_block_command;
+constexpr char NativeProcessLinux::Monitor::end_block_command;
+
+Error
+NativeProcessLinux::Monitor::Initialize()
+{
+    Error error;
+
+    // We get a SIGCHLD every time something interesting happens with the inferior. We shall be
+    // listening for these signals over a signalfd file descriptors. This allows us to wait for
+    // multiple kinds of events with select.
+    sigset_t signals;
+    sigemptyset(&signals);
+    sigaddset(&signals, SIGCHLD);
+    m_signal_fd = signalfd(-1, &signals, SFD_NONBLOCK | SFD_CLOEXEC);
+    if (m_signal_fd < 0)
+    {
+        return Error("NativeProcessLinux::Monitor::%s failed due to signalfd failure. Monitoring the inferior will be impossible: %s",
+                    __FUNCTION__, strerror(errno));
+
+    }
+
+    if (pipe2(m_pipefd, O_CLOEXEC) == -1)
+    {
+        error.SetErrorToErrno();
+        return error;
+    }
+
+    if ((error = EnsureFDFlags(m_pipefd[READ], O_NONBLOCK)).Fail()) {
+        return error;
+    }
+
+    static const char g_thread_name[] = "lldb.process.nativelinux.monitor";
+    m_thread = ThreadLauncher::LaunchThread(g_thread_name, Monitor::RunMonitor, this, nullptr);
+    if (!m_thread.IsJoinable())
+        return Error("Failed to create monitor thread for NativeProcessLinux.");
+
+    // Wait for initial operation to complete.
+    return WaitForAck();
+}
+
+Error
+NativeProcessLinux::Monitor::DoOperation(const Operation &op)
+{
+    if (m_thread.EqualsThread(pthread_self())) {
+        // If we're on the Monitor thread, we can simply execute the operation.
+        return op();
+    }
+
+    // Otherwise we need to pass the operation to the Monitor thread so it can handle it.
+    Mutex::Locker lock(m_operation_mutex);
+
+    m_operation = &op;
+
+    // notify the thread that an operation is ready to be processed
+    write(m_pipefd[WRITE], &operation_command, sizeof operation_command);
+
+    return WaitForAck();
+}
+
+void
+NativeProcessLinux::Monitor::Terminate()
+{
+    if (m_pipefd[WRITE] >= 0)
+    {
+        close(m_pipefd[WRITE]);
+        m_pipefd[WRITE] = -1;
+    }
+    if (m_thread.IsJoinable())
+        m_thread.Join(nullptr);
+}
+
+NativeProcessLinux::Monitor::~Monitor()
+{
+    Terminate();
+    if (m_pipefd[READ] >= 0)
+        close(m_pipefd[READ]);
+    if (m_signal_fd >= 0)
+        close(m_signal_fd);
+    sem_destroy(&m_operation_sem);
+}
+
+void
+NativeProcessLinux::Monitor::HandleSignals()
+{
+    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+    // We don't really care about the content of the SIGCHLD siginfo structure, as we will get
+    // all the information from waitpid(). We just need to read all the signals so that we can
+    // sleep next time we reach select().
+    while (true)
+    {
+        signalfd_siginfo info;
+        ssize_t size = read(m_signal_fd, &info, sizeof info);
+        if (size == -1)
+        {
+            if (errno == EAGAIN || errno == EWOULDBLOCK)
+                break; // We are done.
+            if (errno == EINTR)
+                continue;
+            if (log)
+                log->Printf("NativeProcessLinux::Monitor::%s reading from signalfd file descriptor failed: %s",
+                        __FUNCTION__, strerror(errno));
+            break;
+        }
+        if (size != sizeof info)
+        {
+            // We got incomplete information structure. This should not happen, let's just log
+            // that.
+            if (log)
+                log->Printf("NativeProcessLinux::Monitor::%s reading from signalfd file descriptor returned incomplete data: "
+                        "structure size is %zd, read returned %zd bytes",
+                        __FUNCTION__, sizeof info, size);
+            break;
+        }
+        if (log)
+            log->Printf("NativeProcessLinux::Monitor::%s received signal %s(%d).", __FUNCTION__,
+                Host::GetSignalAsCString(info.ssi_signo), info.ssi_signo);
+    }
+}
+
+void
+NativeProcessLinux::Monitor::HandleWait()
+{
+    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+    // Process all pending waitpid notifications.
+    while (true)
+    {
+        int status = -1;
+        ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
+
+        if (wait_pid == 0)
+            break; // We are done.
+
+        if (wait_pid == -1)
+        {
+            if (errno == EINTR)
+                continue;
+
+            if (log)
+              log->Printf("NativeProcessLinux::Monitor::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s",
+                      __FUNCTION__, strerror(errno));
+            break;
+        }
+
+        bool exited = false;
+        int signal = 0;
+        int exit_status = 0;
+        const char *status_cstr = NULL;
+        if (WIFSTOPPED(status))
+        {
+            signal = WSTOPSIG(status);
+            status_cstr = "STOPPED";
+        }
+        else if (WIFEXITED(status))
+        {
+            exit_status = WEXITSTATUS(status);
+            status_cstr = "EXITED";
+            exited = true;
+        }
+        else if (WIFSIGNALED(status))
+        {
+            signal = WTERMSIG(status);
+            status_cstr = "SIGNALED";
+            if (wait_pid == m_child_pid) {
+                exited = true;
+                exit_status = -1;
+            }
+        }
+        else
+            status_cstr = "(\?\?\?)";
+
+        if (log)
+            log->Printf("NativeProcessLinux::Monitor::%s: waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG)"
+                "=> pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
+                __FUNCTION__, wait_pid, status, status_cstr, signal, exit_status);
+
+        m_native_process->MonitorCallback (wait_pid, exited, signal, exit_status);
+    }
+}
+
+bool
+NativeProcessLinux::Monitor::HandleCommands()
+{
+    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+    while (true)
+    {
+        char command = 0;
+        ssize_t size = read(m_pipefd[READ], &command, sizeof command);
+        if (size == -1)
+        {
+            if (errno == EAGAIN || errno == EWOULDBLOCK)
+                return false;
+            if (errno == EINTR)
+                continue;
+            if (log)
+                log->Printf("NativeProcessLinux::Monitor::%s exiting because read from command file descriptor failed: %s", __FUNCTION__, strerror(errno));
+            return true;
+        }
+        if (size == 0) // end of file - write end closed
+        {
+            if (log)
+                log->Printf("NativeProcessLinux::Monitor::%s exit command received, exiting...", __FUNCTION__);
+            assert(m_operation_nesting_level == 0 && "Unbalanced begin/end block commands detected");
+            return true; // We are done.
+        }
+
+        switch (command)
+        {
+        case operation_command:
+            m_operation_error = (*m_operation)();
+            break;
+        case begin_block_command:
+            ++m_operation_nesting_level;
+            break;
+        case end_block_command:
+            assert(m_operation_nesting_level > 0);
+            --m_operation_nesting_level;
+            break;
+        default:
+            if (log)
+                log->Printf("NativeProcessLinux::Monitor::%s received unknown command '%c'",
+                        __FUNCTION__, command);
+        }
+
+        // notify calling thread that the command has been processed
+        sem_post(&m_operation_sem);
+    }
+}
+
+void
+NativeProcessLinux::Monitor::MainLoop()
+{
+    ::pid_t child_pid = (*m_initial_operation_up)(m_operation_error);
+    m_initial_operation_up.reset();
+    m_child_pid = child_pid;
+    sem_post(&m_operation_sem);
+
+    while (true)
+    {
+        fd_set fds;
+        FD_ZERO(&fds);
+        // Only process waitpid events if we are outside of an operation block. Any pending
+        // events will be processed after we leave the block.
+        if (m_operation_nesting_level == 0)
+            FD_SET(m_signal_fd, &fds);
+        FD_SET(m_pipefd[READ], &fds);
+
+        int max_fd = std::max(m_signal_fd, m_pipefd[READ]) + 1;
+        int r = select(max_fd, &fds, nullptr, nullptr, nullptr);
+        if (r < 0)
+        {
+            Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+            if (log)
+                log->Printf("NativeProcessLinux::Monitor::%s exiting because select failed: %s",
+                        __FUNCTION__, strerror(errno));
+            return;
+        }
+
+        if (FD_ISSET(m_pipefd[READ], &fds))
+        {
+            if (HandleCommands())
+                return;
+        }
+
+        if (FD_ISSET(m_signal_fd, &fds))
+        {
+            HandleSignals();
+            HandleWait();
+        }
+    }
+}
+
+Error
+NativeProcessLinux::Monitor::WaitForAck()
+{
+    Error error;
+    while (sem_wait(&m_operation_sem) != 0)
+    {
+        if (errno == EINTR)
+            continue;
+
+        error.SetErrorToErrno();
+        return error;
+    }
+
+    return m_operation_error;
+}
+
+void *
+NativeProcessLinux::Monitor::RunMonitor(void *arg)
+{
+    static_cast<Monitor *>(arg)->MainLoop();
+    return nullptr;
+}
+
+
 NativeProcessLinux::LaunchArgs::LaunchArgs(Module *module,
                                        char const **argv,
                                        char const **envp,
@@ -269,7 +819,6 @@ Error
 NativeProcessProtocol::Launch (
     ProcessLaunchInfo &launch_info,
     NativeProcessProtocol::NativeDelegate &native_delegate,
-    MainLoop &mainloop,
     NativeProcessProtocolSP &native_process_sp)
 {
     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -356,7 +905,6 @@ NativeProcessProtocol::Launch (
     }
 
     std::static_pointer_cast<NativeProcessLinux> (native_process_sp)->LaunchInferior (
-            mainloop,
             exe_module_sp.get(),
             launch_info.GetArguments ().GetConstArgumentVector (),
             launch_info.GetEnvironmentEntries ().GetConstArgumentVector (),
@@ -384,7 +932,6 @@ Error
 NativeProcessProtocol::Attach (
     lldb::pid_t pid,
     NativeProcessProtocol::NativeDelegate &native_delegate,
-    MainLoop &mainloop,
     NativeProcessProtocolSP &native_process_sp)
 {
     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
@@ -411,7 +958,7 @@ NativeProcessProtocol::Attach (
         return error;
     }
 
-    native_process_linux_sp->AttachToInferior (mainloop, pid, error);
+    native_process_linux_sp->AttachToInferior (pid, error);
     if (!error.Success ())
         return error;
 
@@ -432,9 +979,12 @@ NativeProcessLinux::NativeProcessLinux (
 {
 }
 
+//------------------------------------------------------------------------------
+// NativeProcessLinux spawns a new thread which performs all operations on the inferior process.
+// Refer to Monitor and Operation classes to see why this is necessary.
+//------------------------------------------------------------------------------
 void
 NativeProcessLinux::LaunchInferior (
-    MainLoop &mainloop,
     Module *module,
     const char *argv[],
     const char *envp[],
@@ -445,11 +995,6 @@ NativeProcessLinux::LaunchInferior (
     const ProcessLaunchInfo &launch_info,
     Error &error)
 {
-    m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD,
-            [this] (MainLoopBase &) { SigchldHandler(); }, error);
-    if (! m_sigchld_handle)
-        return;
-
     if (module)
         m_arch = module->GetArchitecture ();
 
@@ -463,21 +1008,18 @@ NativeProcessLinux::LaunchInferior (
                        working_dir,
                        launch_info));
 
-    Launch(args.get(), error);
+    StartMonitorThread ([&] (Error &e) { return Launch(args.get(), e); }, error);
+    if (!error.Success ())
+        return;
 }
 
 void
-NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error)
+NativeProcessLinux::AttachToInferior (lldb::pid_t pid, Error &error)
 {
     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
     if (log)
         log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid);
 
-    m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD,
-            [this] (MainLoopBase &) { SigchldHandler(); }, error);
-    if (! m_sigchld_handle)
-        return;
-
     // We can use the Host for everything except the ResolveExecutable portion.
     PlatformSP platform_sp = Platform::GetHostPlatform ();
     if (!platform_sp)
@@ -515,7 +1057,15 @@ NativeProcessLinux::AttachToInferior (Ma
     m_pid = pid;
     SetState(eStateAttaching);
 
-    Attach(pid, error);
+    StartMonitorThread ([=] (Error &e) { return Attach(pid, e); }, error);
+    if (!error.Success ())
+        return;
+}
+
+void
+NativeProcessLinux::Terminate ()
+{
+    m_monitor_up->Terminate();
 }
 
 ::pid_t
@@ -1737,6 +2287,7 @@ NativeProcessLinux::Resume (const Resume
 
     bool software_single_step = !SupportHardwareSingleStepping();
 
+    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
     Mutex::Locker locker (m_threads_mutex);
 
     if (software_single_step)
@@ -1856,7 +2407,7 @@ NativeProcessLinux::Detach ()
         error = Detach (GetID ());
 
     // Stop monitoring the inferior.
-    m_sigchld_handle.reset();
+    m_monitor_up->Terminate();
 
     // No error.
     return error;
@@ -1891,6 +2442,7 @@ NativeProcessLinux::Interrupt ()
     if (log)
         log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__);
 
+    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
     Mutex::Locker locker (m_threads_mutex);
 
     for (auto thread_sp : m_threads)
@@ -2546,6 +3098,24 @@ NativeProcessLinux::GetCrashReasonForSIG
 #endif
 
 Error
+NativeProcessLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
+{
+    // The base SetWatchpoint will end up executing monitor operations. Let's lock the monitor
+    // for it.
+    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
+    return NativeProcessProtocol::SetWatchpoint(addr, size, watch_flags, hardware);
+}
+
+Error
+NativeProcessLinux::RemoveWatchpoint (lldb::addr_t addr)
+{
+    // The base RemoveWatchpoint will end up executing monitor operations. Let's lock the monitor
+    // for it.
+    Monitor::ScopedOperationLock monitor_lock(*m_monitor_up);
+    return NativeProcessProtocol::RemoveWatchpoint(addr);
+}
+
+Error
 NativeProcessLinux::ReadMemory (lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
 {
     if (ProcessVmReadvSupported()) {
@@ -2574,52 +3144,7 @@ NativeProcessLinux::ReadMemory (lldb::ad
         //     the call failed for some reason, let's retry the read using ptrace api.
     }
 
-    unsigned char *dst = static_cast<unsigned char*>(buf);
-    size_t remainder;
-    long data;
-
-    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
-    if (log)
-        ProcessPOSIXLog::IncNestLevel();
-    if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
-        log->Printf ("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, (void*)addr, buf, size);
-
-    for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
-    {
-        Error error = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, GetID(), (void*)addr, nullptr, 0, &data);
-        if (error.Fail())
-        {
-            if (log)
-                ProcessPOSIXLog::DecNestLevel();
-            return error;
-        }
-
-        remainder = size - bytes_read;
-        remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
-
-        // Copy the data into our buffer
-        for (unsigned i = 0; i < remainder; ++i)
-            dst[i] = ((data >> i*8) & 0xFF);
-
-        if (log && ProcessPOSIXLog::AtTopNestLevel() &&
-                (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
-                        (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
-                                size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
-        {
-            uintptr_t print_dst = 0;
-            // Format bytes from data by moving into print_dst for log output
-            for (unsigned i = 0; i < remainder; ++i)
-                print_dst |= (((data >> i*8) & 0xFF) << i*8);
-            log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
-                    (void*)addr, print_dst, (unsigned long)data);
-        }
-        addr += k_ptrace_word_size;
-        dst += k_ptrace_word_size;
-    }
-
-    if (log)
-        ProcessPOSIXLog::DecNestLevel();
-    return Error();
+    return DoOperation([&] { return DoReadMemory(GetID(), addr, buf, size, bytes_read); });
 }
 
 Error
@@ -2633,79 +3158,7 @@ NativeProcessLinux::ReadMemoryWithoutTra
 Error
 NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)
 {
-    const unsigned char *src = static_cast<const unsigned char*>(buf);
-    size_t remainder;
-    Error error;
-
-    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL));
-    if (log)
-        ProcessPOSIXLog::IncNestLevel();
-    if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY))
-        log->Printf ("NativeProcessLinux::%s(%p, %p, %" PRIu64 ")", __FUNCTION__, (void*)addr, buf, size);
-
-    for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
-    {
-        remainder = size - bytes_written;
-        remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
-
-        if (remainder == k_ptrace_word_size)
-        {
-            unsigned long data = 0;
-            for (unsigned i = 0; i < k_ptrace_word_size; ++i)
-                data |= (unsigned long)src[i] << i*8;
-
-            if (log && ProcessPOSIXLog::AtTopNestLevel() &&
-                    (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
-                            (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
-                                    size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
-                log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
-                        (void*)addr, *(const unsigned long*)src, data);
-
-            error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void*)addr, (void*)data);
-            if (error.Fail())
-            {
-                if (log)
-                    ProcessPOSIXLog::DecNestLevel();
-                return error;
-            }
-        }
-        else
-        {
-            unsigned char buff[8];
-            size_t bytes_read;
-            error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read);
-            if (error.Fail())
-            {
-                if (log)
-                    ProcessPOSIXLog::DecNestLevel();
-                return error;
-            }
-
-            memcpy(buff, src, remainder);
-
-            size_t bytes_written_rec;
-            error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec);
-            if (error.Fail())
-            {
-                if (log)
-                    ProcessPOSIXLog::DecNestLevel();
-                return error;
-            }
-
-            if (log && ProcessPOSIXLog::AtTopNestLevel() &&
-                    (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) ||
-                            (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) &&
-                                    size <= POSIX_LOG_MEMORY_SHORT_BYTES)))
-                log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__,
-                        (void*)addr, *(const unsigned long*)src, *(unsigned long*)buff);
-        }
-
-        addr += k_ptrace_word_size;
-        src += k_ptrace_word_size;
-    }
-    if (log)
-        ProcessPOSIXLog::DecNestLevel();
-    return error;
+    return DoOperation([&] { return DoWriteMemory(GetID(), addr, buf, size, bytes_written); });
 }
 
 Error
@@ -2724,7 +3177,7 @@ NativeProcessLinux::Resume (lldb::tid_t
     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
         data = signo;
 
-    Error error = PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data);
+    Error error = DoOperation([&] { return PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data); });
 
     if (log)
         log->Printf ("NativeProcessLinux::%s() resuming thread = %"  PRIu64 " result = %s", __FUNCTION__, tid, error.Success() ? "true" : "false");
@@ -2739,19 +3192,19 @@ NativeProcessLinux::SingleStep(lldb::tid
     if (signo != LLDB_INVALID_SIGNAL_NUMBER)
         data = signo;
 
-    return PtraceWrapper(PTRACE_SINGLESTEP, tid, nullptr, (void*)data);
+    return DoOperation([&] { return PtraceWrapper(PTRACE_SINGLESTEP, tid, nullptr, (void*)data); });
 }
 
 Error
 NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo)
 {
-    return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo);
+    return DoOperation([&] { return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); });
 }
 
 Error
 NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message)
 {
-    return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message);
+    return DoOperation([&] { return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); });
 }
 
 Error
@@ -2760,7 +3213,7 @@ NativeProcessLinux::Detach(lldb::tid_t t
     if (tid == LLDB_INVALID_THREAD_ID)
         return Error();
 
-    return PtraceWrapper(PTRACE_DETACH, tid);
+    return DoOperation([&] { return PtraceWrapper(PTRACE_DETACH, tid); });
 }
 
 bool
@@ -2777,6 +3230,16 @@ NativeProcessLinux::DupDescriptor(const
     return (close(target_fd) == -1) ? false : true;
 }
 
+void
+NativeProcessLinux::StartMonitorThread(const InitialOperation &initial_operation, Error &error)
+{
+    m_monitor_up.reset(new Monitor(initial_operation, this));
+    error = m_monitor_up->Initialize();
+    if (error.Fail()) {
+        m_monitor_up.reset();
+    }
+}
+
 bool
 NativeProcessLinux::HasThreadNoLock (lldb::tid_t thread_id)
 {
@@ -3245,65 +3708,10 @@ NativeProcessLinux::ThreadWasCreated (ll
     }
 }
 
-void
-NativeProcessLinux::SigchldHandler()
+Error
+NativeProcessLinux::DoOperation(const Operation &op)
 {
-    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-    // Process all pending waitpid notifications.
-    while (true)
-    {
-        int status = -1;
-        ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
-
-        if (wait_pid == 0)
-            break; // We are done.
-
-        if (wait_pid == -1)
-        {
-            if (errno == EINTR)
-                continue;
-
-            Error error(errno, eErrorTypePOSIX);
-            if (log)
-                log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG) failed: %s",
-                        __FUNCTION__, error.AsCString());
-            break;
-        }
-
-        bool exited = false;
-        int signal = 0;
-        int exit_status = 0;
-        const char *status_cstr = nullptr;
-        if (WIFSTOPPED(status))
-        {
-            signal = WSTOPSIG(status);
-            status_cstr = "STOPPED";
-        }
-        else if (WIFEXITED(status))
-        {
-            exit_status = WEXITSTATUS(status);
-            status_cstr = "EXITED";
-            exited = true;
-        }
-        else if (WIFSIGNALED(status))
-        {
-            signal = WTERMSIG(status);
-            status_cstr = "SIGNALED";
-            if (wait_pid == static_cast<::pid_t>(GetID())) {
-                exited = true;
-                exit_status = -1;
-            }
-        }
-        else
-            status_cstr = "(\?\?\?)";
-
-        if (log)
-            log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | __WNOTHREAD | WNOHANG)"
-                "=> pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
-                __FUNCTION__, wait_pid, status, status_cstr, signal, exit_status);
-
-        MonitorCallback (wait_pid, exited, signal, exit_status);
-    }
+    return m_monitor_up->DoOperation(op);
 }
 
 // Wrapper for ptrace to catch errors and log calls.

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h Thu Jul 16 03:45:03 2015
@@ -43,16 +43,25 @@ namespace process_linux {
         friend Error
         NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
                 NativeDelegate &native_delegate,
-                MainLoop &mainloop,
                 NativeProcessProtocolSP &process_sp);
 
         friend Error
         NativeProcessProtocol::Attach (lldb::pid_t pid,
-                NativeProcessProtocol::NativeDelegate &native_delegate,
-                MainLoop &mainloop,
-                NativeProcessProtocolSP &process_sp);
+            NativeProcessProtocol::NativeDelegate &native_delegate,
+            NativeProcessProtocolSP &native_process_sp);
 
     public:
+        //------------------------------------------------------------------------------
+        /// @class Operation
+        /// @brief Represents a NativeProcessLinux operation.
+        ///
+        /// Under Linux, it is not possible to ptrace() from any other thread but the
+        /// one that spawned or attached to the process from the start.  Therefore, when
+        /// a NativeProcessLinux is asked to deliver or change the state of an inferior
+        /// process the operation must be "funneled" to a specific thread to perform the
+        /// task.
+        typedef std::function<Error()> Operation;
+
         // ---------------------------------------------------------------------
         // NativeProcessProtocol Interface
         // ---------------------------------------------------------------------
@@ -104,9 +113,18 @@ namespace process_linux {
         Error
         SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override;
 
+        Error
+        SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override;
+
+        Error
+        RemoveWatchpoint (lldb::addr_t addr) override;
+
         void
         DoStopIDBumped (uint32_t newBumpId) override;
 
+        void
+        Terminate () override;
+
         Error
         GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override;
 
@@ -116,6 +134,9 @@ namespace process_linux {
         // ---------------------------------------------------------------------
         // Interface used by NativeRegisterContext-derived classes.
         // ---------------------------------------------------------------------
+        Error
+        DoOperation(const Operation &op);
+
         static Error
         PtraceWrapper(int req,
                       lldb::pid_t pid,
@@ -133,9 +154,12 @@ namespace process_linux {
 
     private:
 
-        MainLoop::SignalHandleUP m_sigchld_handle;
+        class Monitor;
+
         ArchSpec m_arch;
 
+        std::unique_ptr<Monitor> m_monitor_up;
+
         LazyBool m_supports_mem_region;
         std::vector<MemoryRegionInfo> m_mem_region_cache;
         Mutex m_mem_region_cache_mutex;
@@ -182,7 +206,6 @@ namespace process_linux {
         /// implementation of Process::DoLaunch.
         void
         LaunchInferior (
-            MainLoop &mainloop,
             Module *module,
             char const *argv[],
             char const *envp[],
@@ -196,7 +219,10 @@ namespace process_linux {
         /// Attaches to an existing process.  Forms the
         /// implementation of Process::DoAttach
         void
-        AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error);
+        AttachToInferior (lldb::pid_t pid, Error &error);
+
+        void
+        StartMonitorThread(const InitialOperation &operation, Error &error);
 
         ::pid_t
         Launch(LaunchArgs *args, Error &error);
@@ -344,9 +370,6 @@ namespace process_linux {
         void
         ThreadWasCreated (lldb::tid_t tid);
 
-        void
-        SigchldHandler();
-
         // Member variables.
         PendingNotificationUP m_pending_notification_up;
     };

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp Thu Jul 16 03:45:03 2015
@@ -50,7 +50,14 @@ NativeRegisterContextLinux::ReadRegister
     if (!reg_info)
         return Error("register %" PRIu32 " not found", reg_index);
 
-    return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value);
+    NativeProcessProtocolSP process_sp(m_thread.GetProcess());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+    return process_p->DoOperation([&] {
+        return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, reg_info->byte_size, reg_value);
+    });
 }
 
 Error
@@ -101,70 +108,111 @@ NativeRegisterContextLinux::WriteRegiste
         }
     }
 
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+
     const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
     assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
     if (!register_to_write_info_p)
         return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
 
-    return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+    return process_p->DoOperation([&] {
+        return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value);
+    });
 }
 
 Error
 NativeRegisterContextLinux::ReadGPR()
 {
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+
     void* buf = GetGPRBuffer();
     if (!buf)
         return Error("GPR buffer is NULL");
     size_t buf_size = GetGPRSize();
 
-    return DoReadGPR(buf, buf_size);
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+    return process_p->DoOperation([&] { return DoReadGPR(buf, buf_size); });
 }
 
 Error
 NativeRegisterContextLinux::WriteGPR()
 {
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+
     void* buf = GetGPRBuffer();
     if (!buf)
         return Error("GPR buffer is NULL");
     size_t buf_size = GetGPRSize();
 
-    return DoWriteGPR(buf, buf_size);
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+    return process_p->DoOperation([&] { return DoWriteGPR(buf, buf_size); });
 }
 
 Error
 NativeRegisterContextLinux::ReadFPR()
 {
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+
     void* buf = GetFPRBuffer();
     if (!buf)
         return Error("GPR buffer is NULL");
     size_t buf_size = GetFPRSize();
 
-    return DoReadFPR(buf, buf_size);
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+    return process_p->DoOperation([&] { return DoReadFPR(buf, buf_size); });
 }
 
 Error
 NativeRegisterContextLinux::WriteFPR()
 {
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+
     void* buf = GetFPRBuffer();
     if (!buf)
         return Error("GPR buffer is NULL");
     size_t buf_size = GetFPRSize();
 
-    return DoWriteFPR(buf, buf_size);
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+    return process_p->DoOperation([&] { return DoWriteFPR(buf, buf_size); });
 }
 
 Error
 NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
 {
-    return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
-            static_cast<void *>(&regset), buf, buf_size);
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+
+    return process_p->DoOperation([&] {
+        return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(),
+                static_cast<void *>(&regset), buf, buf_size);
+    });
 }
 
 Error
 NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
 {
-    return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
-            static_cast<void *>(&regset), buf, buf_size);
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+    NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+
+    return process_p->DoOperation([&] {
+        return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
+                static_cast<void *>(&regset), buf, buf_size);
+    });
 }
 
 Error

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp Thu Jul 16 03:45:03 2015
@@ -715,23 +715,29 @@ Error
 NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count,
                                                         unsigned int &break_count)
 {
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
     ::pid_t tid = m_thread.GetID();
 
-    int regset = NT_ARM_HW_WATCH;
-    struct iovec ioVec;
-    struct user_hwdebug_state dreg_state;
-    Error error;
-
-    ioVec.iov_base = &dreg_state;
-    ioVec.iov_len = sizeof (dreg_state);
-    error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, ioVec.iov_len);
-    watch_count = dreg_state.dbg_info & 0xff;
-
-    regset = NT_ARM_HW_BREAK;
-    error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, ioVec.iov_len);
-    break_count = dreg_state.dbg_info & 0xff;
+    return process_p->DoOperation([&] {
+        int regset = NT_ARM_HW_WATCH;
+        struct iovec ioVec;
+        struct user_hwdebug_state dreg_state;
+        Error error;
+
+        ioVec.iov_base = &dreg_state;
+        ioVec.iov_len = sizeof (dreg_state);
+        error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, ioVec.iov_len);
+        watch_count = dreg_state.dbg_info & 0xff;
+
+        regset = NT_ARM_HW_BREAK;
+        error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset, &ioVec, ioVec.iov_len);
+        break_count = dreg_state.dbg_info & 0xff;
 
-    return error;
+        return error;
+    });
 }
 
 Error
@@ -740,26 +746,33 @@ NativeRegisterContextLinux_arm64::WriteH
                                                          int type,
                                                          int count)
 {
-    struct iovec ioVec;
-    struct user_hwdebug_state dreg_state;
-    Error error;
-
-    memset (&dreg_state, 0, sizeof (dreg_state));
-    ioVec.iov_base = &dreg_state;
-    ioVec.iov_len = sizeof (dreg_state);
-
-    if (type == 0)
-        type = NT_ARM_HW_WATCH;
-    else
-        type = NT_ARM_HW_BREAK;
-
-    for (int i = 0; i < count; i++)
-    {
-        dreg_state.dbg_regs[i].addr = addr_buf[i];
-        dreg_state.dbg_regs[i].ctrl = cntrl_buf[i];
-    }
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+    if (!process_sp)
+        return Error("NativeProcessProtocol is NULL");
+    NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
+
+    return process_p->DoOperation([&] {
+        struct iovec ioVec;
+        struct user_hwdebug_state dreg_state;
+        Error error;
+
+        memset (&dreg_state, 0, sizeof (dreg_state));
+        ioVec.iov_base = &dreg_state;
+        ioVec.iov_len = sizeof (dreg_state);
+
+        if (type == 0)
+            type = NT_ARM_HW_WATCH;
+        else
+            type = NT_ARM_HW_BREAK;
+
+        for (int i = 0; i < count; i++)
+        {
+            dreg_state.dbg_regs[i].addr = addr_buf[i];
+            dreg_state.dbg_regs[i].ctrl = cntrl_buf[i];
+        }
 
-    return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &type, &ioVec, ioVec.iov_len);
+        return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &type, &ioVec, ioVec.iov_len);
+    });
 }
 
 Error

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp Thu Jul 16 03:45:03 2015
@@ -877,13 +877,19 @@ NativeRegisterContextLinux_mips64::IsWat
 
     // reading the current state of watch regs
     struct pt_watch_regs watch_readback;
-    Error error =  DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+    Error error = process_p->DoOperation([&] {
+        return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+    });
 
     if (GetWatchHi (&watch_readback, wp_index) & (IRW))
     {
         // clear hit flag in watchhi 
         SetWatchHi (&watch_readback, wp_index, (GetWatchHi (&watch_readback, wp_index) & ~(IRW)));
-        DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+        process_p->DoOperation([&] {
+            return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&watch_readback));
+        });
      
         is_hit = true;
         return error;
@@ -924,7 +930,11 @@ NativeRegisterContextLinux_mips64::Clear
 
     struct pt_watch_regs regs;
     // First reading the current state of watch regs
-    DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void*>(&regs));
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+    process_p->DoOperation([&] {
+        return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void*>(&regs));
+    });
 
     if (regs.style == pt_watch_style_mips32)
     {
@@ -939,7 +949,9 @@ NativeRegisterContextLinux_mips64::Clear
         regs.mips64.watch_masks[wp_index] = default_watch_regs.mips64.watch_masks[wp_index];
     }
 
-    Error error = DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+    Error error = process_p->DoOperation([&] {
+        return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+    });
     if(!error.Fail())
     {
         hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
@@ -951,7 +963,11 @@ NativeRegisterContextLinux_mips64::Clear
 Error
 NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints()
 {
-    return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&default_watch_regs));
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    NativeProcessLinux *const process_p = static_cast<NativeProcessLinux *> (process_sp.get ());
+    return process_p->DoOperation([&] {
+        return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&default_watch_regs));
+    });
 }
 
 Error
@@ -970,7 +986,11 @@ NativeRegisterContextLinux_mips64::SetHa
     struct pt_watch_regs regs;
 
     // First reading the current state of watch regs
-    DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+    NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+    NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+    process_p->DoOperation([&] {
+        return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+    });
 
     // Try if a new watch point fits in this state
     int index = GetVacantWatchIndex (&regs, addr, size, watch_flags, NumSupportedHardwareWatchpoints());
@@ -981,7 +1001,9 @@ NativeRegisterContextLinux_mips64::SetHa
 
 
     // It fits, so we go ahead with updating the state of watch regs 
-    DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+    process_p->DoOperation([&] {
+        return DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+    });
 
     // Storing exact address  
     hw_addr_map[index] = addr; 
@@ -1005,7 +1027,17 @@ NativeRegisterContextLinux_mips64::NumSu
     static int num_valid = 0;
     if (!num_valid)
     {
-        DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+        NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+        if (!process_sp)
+        {
+            printf ("NativeProcessProtocol is NULL");
+            return 0;
+        }
+
+        NativeProcessLinux *const process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+        process_p->DoOperation([&] {
+            return DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(&regs));
+        });
         default_watch_regs = regs; // Keeping default watch regs values for future use
         switch (regs.style)
         {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Thu Jul 16 03:45:03 2015
@@ -96,6 +96,20 @@ GDBRemoteCommunicationServerLLGS::GDBRem
     RegisterPacketHandlers();
 }
 
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteCommunicationServerLLGS::~GDBRemoteCommunicationServerLLGS()
+{
+    Mutex::Locker locker (m_debugged_process_mutex);
+
+    if (m_debugged_process_sp)
+    {
+        m_debugged_process_sp->Terminate ();
+        m_debugged_process_sp.reset ();
+    }
+}
+
 void
 GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
 {
@@ -209,7 +223,6 @@ GDBRemoteCommunicationServerLLGS::Launch
         error = NativeProcessProtocol::Launch(
             m_process_launch_info,
             *this,
-            m_mainloop,
             m_debugged_process_sp);
     }
 
@@ -295,7 +308,7 @@ GDBRemoteCommunicationServerLLGS::Attach
         }
 
         // Try to attach.
-        error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp);
+        error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp);
         if (!error.Success ())
         {
             fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h?rev=242391&r1=242390&r2=242391&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h Thu Jul 16 03:45:03 2015
@@ -42,6 +42,9 @@ public:
     //------------------------------------------------------------------
     GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop);
 
+    virtual
+    ~GDBRemoteCommunicationServerLLGS();
+
     //------------------------------------------------------------------
     /// Specify the program to launch and its arguments.
     ///





More information about the lldb-commits mailing list