<div dir="ltr"><p style="margin:0px;font-size:12px;font-family:Helvetica">Hi,</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">I have recently built lldb with an automated tool “ThreadSanitizer( or tsan)” designed to detect race conditions and similar concurrency problems. It turned up a number of potential issues. Some may be real, others are probably not an issue in practice. I submitted a patch which fixed a few, either using a mutex, or std::atomic< >. The process of manually analyzing each warning involves a lot of time consuming legwork. In many cases, the work to quiet the warning would add code complexity and runtime hit that may not be worth it. </p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">I need to back-burner this for a bit and move on tow work on something different. I thought I would post some of my findings here as there may still be some real bugs in there.</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">1. ==========================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Timer.cpp: <b>g_depth </b>: this is a class static variable used in constructor and destructor. Use of a timer object from different threads will have a race.</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">CommandInterpreter::HandleCommand() uses Timer scopedTimer; // called from main</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Disassembler::FindPlugin() uses scoped_timer, called from event handler thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">2. ===========================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Editline.cpp/.h : Editline::Hide(), and other functions use <b>m_getting_line</b> from eventhandler thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">EditLine::GetLine() called from main thread via IOHandlerEditLine::Run()</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">3. ===========================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">IOHandler::Activate(), Deactivate() accesses <b>m_active</b>, called in Debugger::ExecuteIOHandlers() in main thread,</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Debugger::PopIOHandler() can also call those functions from event handler thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">4. ===================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">IOHandlerProcessSTDIO::OpenPipes() will read/write to <b>m_pipe</b> from main thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">IOHandlerProcessSTDIO::Cancel() will call m_pipe.Write() from event handler thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">5. =======================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Process.h: <b>m_private_state_thread</b> - accessed from multiple places from main thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Process::RunThreadPlan(), </p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Process::StartPrivateStateThread(), </p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Process::ControlPrivateStateThread()</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Process::PrivateStateThreadIsValid()</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">and from internal state thread:</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Process::RunPrivateStateThread() clears this value when exiting. I don’t think this is safe in all possible cases</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">6. ===========================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">There is a whole class of problems related to resources created in Process, and used by multiple threads. TSAN complains when the ~Process() destructor is called and destroys those resources. From what I can tell, the threads are typically shut down and not using those resources at that point, but if a thread were to shut itself down asynchronously, I think it is possible for the resources to get destroyed without a formal interlock on those events.</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Things like:</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica"><b>m_public_run_lock</b>.SetStopped();</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica"><b>m_private_state_control_wai</b>t.SetValue (true, eBroadcastAlways);</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica"><b>m_private_state_thread</b>.Reset();</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">called in private state thread</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">In ~Process(), if m_private_state_thread null, it will not call ControlPrivateStateThread() to shut the thread down.</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">7. ============================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Similar to point 5: </p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">ProcessGDBRemote::AsyncThread(), can clear <b>m_async_thread</b> when shutting down, while it is access many places from the main thread.</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">8. ===========================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">Communication::<b>m_read_thread_enabled</b> is read from ReadThread(), but modified from main()</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">9. ============================</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">ProcessGDBRemote::DoDestroy() will call a Socket::Close() from main thread.</p>
<p style="margin:0px;font-size:12px;font-family:Helvetica;min-height:14px"><br></p>
<p style="margin:0px;font-size:12px;font-family:Helvetica">An error condition in reading a socket in the async thread will call Disconnect(), accessing the same socket variable</p><div><br></div></div>