Index: lldb/include/lldb/Core/IOHandler.h
===================================================================
--- lldb/include/lldb/Core/IOHandler.h
+++ lldb/include/lldb/Core/IOHandler.h
@@ -85,17 +85,17 @@
 
   virtual void GotEOF() = 0;
 
-  virtual bool IsActive() { return m_active && !m_done; }
+  virtual bool IsActive();
 
-  virtual void SetIsDone(bool b) { m_done = b; }
+  virtual void SetIsDone(bool b);
 
-  virtual bool GetIsDone() { return m_done; }
+  virtual bool GetIsDone();
 
   Type GetType() const { return m_type; }
 
-  virtual void Activate() { m_active = true; }
+  virtual void Activate();
 
-  virtual void Deactivate() { m_active = false; }
+  virtual void Deactivate();
 
   virtual void TerminalSizeChanged() {}
 
@@ -178,10 +178,12 @@
   Flags m_flags;
   Type m_type;
   void *m_user_data;
+
+private:
+  std::mutex m_control_mutex;
   bool m_done;
   bool m_active;
 
-private:
   IOHandler(const IOHandler &) = delete;
   const IOHandler &operator=(const IOHandler &) = delete;
 };
Index: lldb/source/Core/IOHandler.cpp
===================================================================
--- lldb/source/Core/IOHandler.cpp
+++ lldb/source/Core/IOHandler.cpp
@@ -79,6 +79,31 @@
 
 IOHandler::~IOHandler() = default;
 
+bool IOHandler::IsActive() {
+  std::lock_guard<std::mutex> guard(m_control_mutex);
+  return m_active && !m_done;
+}
+
+void IOHandler::SetIsDone(bool b) {
+  std::lock_guard<std::mutex> guard(m_control_mutex);
+  m_done = b;
+}
+
+bool IOHandler::GetIsDone() {
+  std::lock_guard<std::mutex> guard(m_control_mutex);
+  return m_done;
+}
+
+void IOHandler::Activate() {
+  std::lock_guard<std::mutex> guard(m_control_mutex);
+  m_active = true;
+}
+
+void IOHandler::Deactivate() {
+  std::lock_guard<std::mutex> guard(m_control_mutex);
+  m_active = false;
+}
+
 int IOHandler::GetInputFD() {
   return (m_input_sp ? m_input_sp->GetDescriptor() : -1);
 }
@@ -558,7 +583,7 @@
       StringList lines;
       if (GetLines(lines, interrupted)) {
         if (interrupted) {
-          m_done = m_interrupt_exits;
+          SetIsDone(m_interrupt_exits);
           m_delegate.IOHandlerInputInterrupted(*this, line);
 
         } else {
@@ -566,7 +591,7 @@
           m_delegate.IOHandlerInputComplete(*this, line);
         }
       } else {
-        m_done = true;
+        SetIsDone(true);
       }
     } else {
       if (GetLine(line, interrupted)) {
@@ -575,7 +600,7 @@
         else
           m_delegate.IOHandlerInputComplete(*this, line);
       } else {
-        m_done = true;
+        SetIsDone(true);
       }
     }
   }
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -4398,7 +4398,7 @@
     // interrupt the IOHandlerProcessSTDIO::Run() and we can look at the byte
     // that was written to the pipe and then call
     // m_process->SendAsyncInterrupt() from a much safer location in code.
-    if (m_active) {
+    if (IsActive()) {
       char ch = 'i'; // Send 'i' for interrupt
       size_t bytes_written = 0;
       Status result = m_pipe.Write(&ch, 1, bytes_written);