https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112020-12-14T23:02:44ZRuby Issue Tracking SystemRuby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=892282020-12-14T23:02:44Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul></ul><p>PS This issue is not 100% reproducible, please try to run script several times, thank you.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=892292020-12-14T23:04:10Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul><li><strong>File</strong> <a href="/attachments/8632">Screenshot_20201215_020316.png</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/8632/Screenshot_20201215_020316.png">Screenshot_20201215_020316.png</a> added</li></ul><p>I've added a screenshot from windows virtual machine on mingw64 env.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=904912021-02-18T18:11:02Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul></ul><p>The problem is <code>socklist_insert</code> function, you can just add the following code:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="n">socklist_insert</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"fit %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">is_socket</span><span class="p">(</span><span class="n">TO_SOCKET</span><span class="p">(</span><span class="n">fd</span><span class="p">)));</span>
</code></pre>
<p><code>is_socket</code> has a chance to be false. <code>is_socket</code> is just an alias to <code>socklist_lookup</code>. So we can see that <code>socklist_insert</code> and <code>socklist_lookup</code> somehow used in wrong way.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=904932021-02-18T22:28:19Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul></ul><p>You can easily reproduce this issue by using the following code:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="c1">// socklist_insert(r, 0);</span>
<span class="n">st_data_t</span> <span class="n">data</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">insert_result_0</span> <span class="o">=</span> <span class="n">st_insert</span><span class="p">(</span><span class="n">socklist</span><span class="p">,</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="n">r</span><span class="p">,</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">lookup_result_0</span> <span class="o">=</span> <span class="n">st_lookup</span><span class="p">(</span><span class="n">socklist</span><span class="p">,</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="n">r</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"fit 0 %d %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">insert_result_0</span><span class="p">,</span> <span class="n">lookup_result_0</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">insert_result_1</span> <span class="o">=</span> <span class="n">st_insert</span><span class="p">(</span><span class="n">socklist</span><span class="p">,</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="n">r</span><span class="p">,</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">lookup_result_1</span> <span class="o">=</span> <span class="n">st_lookup</span><span class="p">(</span><span class="n">socklist</span><span class="p">,</span> <span class="p">(</span><span class="n">st_data_t</span><span class="p">)</span><span class="n">r</span><span class="p">,</span> <span class="o">&</span><span class="n">data</span><span class="p">);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">"fit 1 %d %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">insert_result_1</span><span class="p">,</span> <span class="n">lookup_result_1</span><span class="p">);</span>
</code></pre>
<p>It is possible to receive "fit 0 0 0" and "fit 1 1 1" on windows, it means that first <code>st_insert</code> silently failed without error code, but second attempt succeed.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=904952021-02-18T23:42:18Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul></ul><p>I've found the source commit <a href="https://github.com/ruby/ruby/commit/068dd60372d659c97a76224dfce38ed96984cb6f" class="external">068dd60372d659c97a76224dfce38ed96984cb6f</a> where <code>socklist</code> was introduced. <code>st_table</code> is just hash table, it looks like original code provides global <code>socklist</code> hash table and writes into it without any locks. This code was designed for single thread mode only.</p>
<p>Today we can see that multiple <code>GetCurrentThreadId</code> is processing single global <code>socklist</code>, we need to add locks.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=905522021-02-22T22:44:15Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul></ul><p>Added fix <a href="https://github.com/ruby/ruby/pull/4212" class="external">https://github.com/ruby/ruby/pull/4212</a></p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=905672021-02-23T21:10:49Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>Fix merged at <a class="changeset" title="added mutexes for socket and connection lists on win32" href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/0d76636117c99921ac7c43293ba7962d22e72fbd">0d76636117c99921ac7c43293ba7962d22e72fbd</a> .</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=905732021-02-23T22:49:46Zpuchuu (Andrew Aladjev)aladjev.andrew@gmail.com
<ul><li><strong>File</strong> <a href="/attachments/8731">4220.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/8731/4220.patch">4220.patch</a> added</li></ul><p>I've prepared backports for <code>ruby_3_0</code> and <code>ruby_2_7</code> on github, but <code>ruby_2_6</code> is not using github, so i am going to attach it here.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=935062021-08-31T11:45:47Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<ul><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN</i> to <i>2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED</i></li></ul><ul>
<li><a href="https://github.com/ruby/ruby/pull/4218" class="external">https://github.com/ruby/ruby/pull/4218</a></li>
<li><a href="https://github.com/ruby/ruby/pull/4219" class="external">https://github.com/ruby/ruby/pull/4219</a></li>
</ul> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=935562021-09-05T02:44:06Znagachika (Tomoyuki Chikanaga)nagachika00@gmail.com
<ul><li><strong>Backport</strong> changed from <i>2.6: REQUIRED, 2.7: REQUIRED, 3.0: REQUIRED</i> to <i>2.6: REQUIRED, 2.7: REQUIRED, 3.0: DONE</i></li></ul><p>Thank you for preparing backport PRs including bump a patchlevel.<br>
I resolve conflict and merge into ruby_3_0 at 261a0e0e4a3202ca004eddc3cc2cefc9e8d0a90a.</p> Ruby master - Bug #17394: TCPServer is not thread safe on win32https://bugs.ruby-lang.org/issues/17394?journal_id=948732021-11-24T10:08:08Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<ul><li><strong>Backport</strong> changed from <i>2.6: REQUIRED, 2.7: REQUIRED, 3.0: DONE</i> to <i>2.6: REQUIRED, 2.7: DONE, 3.0: DONE</i></li></ul><p>Backported into ruby_2_7 with resolving conflict :)</p>