https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112019-07-07T05:09:10ZRuby Issue Tracking SystemRuby master - Bug #11178: possible bug: a thread killed when waiting on ConditionVariable locks the mutex again before real exithttps://bugs.ruby-lang.org/issues/11178?journal_id=791692019-07-07T05:09:10Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>I don't think this is a bug. Killing a thread requires running ensure blocks until the thread exits, the ensure block for <code>ConditionVariable#wait</code> needs to reacquire the mutex. If it didn't, the method would exit with the mutex not locked, which would cause a <code>ThreadError: Attempt to unlock a mutex which is not locked</code> in <code>Mutex#synchronize</code>. Even if we added code to both <code>ConditionVariable#wait</code> and <code>Mutex#synchronize</code> to recognize killed threads and try to avoid this issue, it wouldn't result in correct behavior for manual ensure blocks. Consider:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span>
<span class="vi">@m</span><span class="p">.</span><span class="nf">synchronize</span> <span class="k">do</span>
<span class="k">begin</span>
<span class="vi">@r</span><span class="p">.</span><span class="nf">wait</span><span class="p">(</span><span class="vi">@m</span><span class="p">)</span>
<span class="k">ensure</span>
<span class="n">some_operation_assuming_mutex_is_locked</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="p">}</span>
</code></pre>
<p>This issue is not specific to ConditionVariable, it can happen anytime a thread tries to lock a mutex in an ensure block. For example, replacing the definition of <code>t</code> in your example with the following code will also trigger it:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span>
<span class="k">begin</span>
<span class="nb">sleep</span> <span class="mi">1</span>
<span class="k">ensure</span>
<span class="vi">@m</span><span class="p">.</span><span class="nf">synchronize</span> <span class="k">do</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="p">}</span>
</code></pre>