https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112011-05-13T08:23:06ZRuby Issue Tracking SystemRuby master - Bug #4681: Timeout.timeout doesn't actually time out?https://bugs.ruby-lang.org/issues/4681?journal_id=169302011-05-13T08:23:06Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>mathew murphy <a href="mailto:meta@pobox.com" class="email">meta@pobox.com</a> wrote:</p>
<blockquote>
<p>This doesn't actually seem to be what it does.</p>
<p>Example code:</p>
<p>#!/usr/bin/ruby</p>
<a name="encoding-UTF-8"></a>
<h1 >encoding: UTF-8<a href="#encoding-UTF-8" class="wiki-anchor">¶</a></h1>
<p>require 'open3'<br>
require 'timeout'</p>
<p>puts "Time out after 2 seconds. Count them..."<br>
result = Timeout.timeout(2) do<br>
stdin, stdout, stderr = Open3.capture3("sleep 30")<br>
output = stdout.read + "\n" + stderr.read<br>
end</p>
</blockquote>
<blockquote>
<p>On my systems, this doesn't time out after 2 seconds. Instead, it runs<br>
for 30 seconds, and then throws an error saying it took longer than 2<br>
seconds.</p>
</blockquote>
<p>It's because open3 has an ensure block where it does Thread#join and<br>
that waits forever, so the timeout thread raised to unblock the<br>
main thread, and then it got stuck again inside the ensure block.</p>
<p>diff --git a/lib/open3.rb b/lib/open3.rb<br>
index b65cb19..d335f9f 100644<br>
--- a/lib/open3.rb<br>
+++ b/lib/open3.rb<br>
@@ -207,6 +207,7 @@ module Open3<br>
begin<br>
return yield(*result)<br>
ensure</p>
<ul>
<li>
<pre><code> p [ :ensure, __FILE__, __LINE__ ]
</code></pre>
parent_io.each{|io| io.close unless io.closed?}<br>
wait_thr.join<br>
end<br>
@@ -702,6 +703,7 @@ module Open3<br>
begin<br>
return yield(*result)<br>
ensure</li>
<li>
<pre><code> p [ :ensure, __FILE__, __LINE__ ]
</code></pre>
parent_io.each{|io| io.close unless io.closed?}<br>
wait_thrs.each {|t| t.join }<br>
end</li>
</ul>
<a name="You-can-work-around-it-by-having-an-extra-timeout-block-ugly"></a>
<h2 >You can work around it by having an extra timeout block (ugly):<a href="#You-can-work-around-it-by-having-an-extra-timeout-block-ugly" class="wiki-anchor">¶</a></h2>
<p>puts "Time out after 2 seconds. Count them..."<br>
Timeout.timeout(2) do<br>
result = Timeout.timeout(2) do<br>
stdin, stdout, stderr = Open3.capture3("sleep 30")<br>
output = stdout.read + "\n" + stderr.read<br>
end<br>
end</p>
<p>But IMHO, timeout is a very fragile module and shouldn't be relied on.</p>
<p>--<br>
Eric Wong</p> Ruby master - Bug #4681: Timeout.timeout doesn't actually time out?https://bugs.ruby-lang.org/issues/4681?journal_id=184612011-06-26T18:58:15Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>akr (Akira Tanaka)</i></li></ul> Ruby master - Bug #4681: Timeout.timeout doesn't actually time out?https://bugs.ruby-lang.org/issues/4681?journal_id=184742011-06-26T19:06:51Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<ul><li><strong>Target version</strong> set to <i>1.9.3</i></li></ul> Ruby master - Bug #4681: Timeout.timeout doesn't actually time out?https://bugs.ruby-lang.org/issues/4681?journal_id=190392011-07-10T15:52:41Zkosaki (Motohiro KOSAKI)kosaki.motohiro@gmail.com
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Rejected</i></li></ul><p>I think Eric described the reason and workaround at commetn#1. IOW, it's spec unfortunately.</p> Ruby master - Bug #4681: Timeout.timeout doesn't actually time out?https://bugs.ruby-lang.org/issues/4681?journal_id=226472011-12-08T13:37:25Zmeta (mathew murphy)meta@pobox.com
<ul></ul><p>Just noting for the benefit of anyone else passing by that I posted a way to do popen3 with timeout at<br>
<a href="https://gist.github.com/1032297" class="external">https://gist.github.com/1032297</a></p>