# Is this a bug in Thread#kill?

**URL:** <https://rubytalk.org/t/is-this-a-bug-in-thread-kill/70554>\
**Category:** ruby-talk\
**Created:** [30 January 2015 07:07 UTC](https://rubytalk.org/t/is-this-a-bug-in-thread-kill/70554 "2015-01-30T07:07:34Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jianjun\_Mao](https://avatars.discourse-cdn.com/v4/letter/j/a587f6/32.png) [@Jianjun\_Mao](https://rubytalk.org/u/Jianjun_Mao)\
**Post date:** [30 January 2015 07:07 UTC](https://rubytalk.org/t/is-this-a-bug-in-thread-kill/70554/1 "2015-01-30T07:07:34Z")

</div>

Hi all,

I find an interesting behavior of Thread#kill, I am not sure if this is a  
bug.  
Please tell me If my test code has any problems.

Require sys-proctable and parallel to test.

require 'open3'  
require 'parallel'  
require 'sys/proctable'

class MemoryOut \< StandardError  
end

jobs = \*(1..10000)

Parallel.map(jobs, :in\_threads=\>20) do  
&nbsp;&nbsp;&nbsp;&nbsp;mem\_thr = Thread.new do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100.times do|i|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sys::ProcTable.ps  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue Errno::ENOENT, Errno::ESRCH  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# ProcTable bug  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i \> 5  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise MemoryOut  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep 0.1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;open\_thr = Thread.new do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Open3.popen2e "sleep 2" do |i, o, w|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w.value  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#mem\_thr.kill  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mem\_thr.join  
&nbsp;&nbsp;&nbsp;&nbsp;rescue MemoryOut  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;open\_thr.join  
end

This program seems OK and I can not find out the problem.

If I add back the commented out line "mem\_thr.kill", then fds opened by  
ProcTable can not be closed, finally causes the error "too many opened  
files".

Use the command "lsof" to check this, can see many files under /proc are  
not closed.  
If I comment out the kill again, everything goes well.

Thanks,  
Jianjun.

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [30 January 2015 08:59 UTC](https://rubytalk.org/t/is-this-a-bug-in-thread-kill/70554/2 "2015-01-30T08:59:05Z")

</div>

> Hi all,
> 
> I find an interesting behavior of Thread#kill, I am not sure if this is a  
> bug.  
> Please tell me If my test code has any problems.

Usage of Thread#kill is discouraged. The proper way to terminate the  
thread would be a thread safe flag that is checked inside the #times loop.  
Wait, since apparently you want to prevent the mem\_thr thread from running  
too long and it's doing a repeated operation I'd just record a target time  
and break if that is passed:

target = Time.now + 2

100.times do  
&nbsp;&nbsp;break if Time.now \> target  
&nbsp;&nbsp;...  
done

Require sys-proctable and parallel to test.

> require 'open3'  
> require 'parallel'  
> require 'sys/proctable'
> 
> class MemoryOut \< StandardError  
> end
> 
> jobs = \*(1..10000)
> 
> Parallel.map(jobs, :in\_threads=\>20) do  
> &nbsp;&nbsp;&nbsp;&nbsp;mem\_thr = Thread.new do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100.times do|i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sys::ProcTable.ps  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue Errno::ENOENT, Errno::ESRCH  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# ProcTable bug  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i \> 5

That condition is odd: why don't you change the number of iterations?

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise MemoryOut

Instead of raising I'd rather break.

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep 0.1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;open\_thr = Thread.new do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Open3.popen2e "sleep 2" do |i, o, w|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w.value  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#mem\_thr.kill  
> &nbsp;&nbsp;&nbsp;&nbsp;end

open\_thr is completely superfluous, why don't you just use sleep()?

> &nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mem\_thr.join  
> &nbsp;&nbsp;&nbsp;&nbsp;rescue MemoryOut

&nbsp;&nbsp;&nbsp;&nbsp;end

> &nbsp;&nbsp;&nbsp;&nbsp;open\_thr.join  
> end
> 
> This program seems OK and I can not find out the problem.

Add

Thread.abort\_on\_exception = true

at the top. That will help debugging.

If I add back the commented out line "mem\_thr.kill", then fds opened by

> ProcTable can not be closed, finally causes the error "too many opened  
> files".
> 
> Use the command "lsof" to check this, can see many files under /proc are  
> not closed.  
> If I comment out the kill again, everything goes well.

I'd say this is rather an issue with Sys::ProcTable than with Thread#kill:  
apparently that does not release resources properly under all  
circumstances. Maybe executing with strace helps to hunt this down.

Kind regards

robert

> **···**
>
> On Fri, Jan 30, 2015 at 8:07 AM, Jianjun Mao \<justmao945@gmail.com\> wrote:
> 
> --  
> [guy, jim, charlie].each {|him| remember.him do |as, often| as.you\_can -  
> without end}  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![Jianjun\_Mao](https://avatars.discourse-cdn.com/v4/letter/j/a587f6/32.png) [@Jianjun\_Mao](https://rubytalk.org/u/Jianjun_Mao)\
**Post date:** [30 January 2015 09:28 UTC](https://rubytalk.org/t/is-this-a-bug-in-thread-kill/70554/3 "2015-01-30T09:28:13Z")

</div>

Thanks for your reply Robert Klemme.

I implemented a function named "shell" to call external executables with  
time and memory limit.  
This piece of code is used to test the problem I described, so you may see  
strange numbers and other things.

Usage of Thread#kill is discouraged. The proper way to terminate the

> thread would be a thread safe flag that is checked inside the #times loop.

Yes, I see now. Thread#kill may prevent releasing sources. When use a flag,  
I can make sure the line to release source is executed.

open\_thr is completely superfluous, why don't you just use sleep()?

Yes, but that's where to execute external executables, just an example here.

I'd say this is rather an issue with Sys::ProcTable than with Thread#kill:

> apparently that does not release resources properly under all  
> circumstances. Maybe executing with strace helps to hunt this down.

You can see the code here

> <https://github.com/djberg96/sys-proctable/blob/main/lib/linux/sys/proctable.rb>

The only function called to read file is IO.read, which guarantees the file  
wil be closed after read. I see now. It seems that IO.read won't release  
resources when the thread is killed, and it is unable to release it, as the  
thread is killed! So that's the problem. You are right, Thread#kill is  
dangerous.

> **···**
>
> On Fri, Jan 30, 2015 at 4:59 PM, Robert Klemme \<shortcutter@googlemail.com\> wrote:
> 
> > On Fri, Jan 30, 2015 at 8:07 AM, Jianjun Mao \<justmao945@gmail.com\> wrote:
> > 
> > > Hi all,
> > > 
> > > I find an interesting behavior of Thread#kill, I am not sure if this is a  
> > > bug.  
> > > Please tell me If my test code has any problems.
> > 
> > Usage of Thread#kill is discouraged. The proper way to terminate the  
> > thread would be a thread safe flag that is checked inside the #times loop.  
> > Wait, since apparently you want to prevent the mem\_thr thread from running  
> > too long and it's doing a repeated operation I'd just record a target time  
> > and break if that is passed:
> > 
> > target = Time.now + 2
> > 
> > 100.times do  
> > &nbsp;&nbsp;break if Time.now \> target  
> > &nbsp;&nbsp;...  
> > done
> > 
> > Require sys-proctable and parallel to test.
> > 
> > > require 'open3'  
> > > require 'parallel'  
> > > require 'sys/proctable'
> > > 
> > > class MemoryOut \< StandardError  
> > > end
> > > 
> > > jobs = \*(1..10000)
> > > 
> > > Parallel.map(jobs, :in\_threads=\>20) do  
> > > &nbsp;&nbsp;&nbsp;&nbsp;mem\_thr = Thread.new do  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100.times do|i|  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sys::ProcTable.ps  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue Errno::ENOENT, Errno::ESRCH  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# ProcTable bug  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i \> 5
> > 
> > That condition is odd: why don't you change the number of iterations?
> > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise MemoryOut
> > 
> > Instead of raising I'd rather break.
> > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep 0.1  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > > &nbsp;&nbsp;&nbsp;&nbsp;end
> > > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;open\_thr = Thread.new do  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Open3.popen2e "sleep 2" do |i, o, w|  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w.value  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#mem\_thr.kill  
> > > &nbsp;&nbsp;&nbsp;&nbsp;end
> > 
> > open\_thr is completely superfluous, why don't you just use sleep()?
> > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;begin  
> > > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mem\_thr.join  
> > > &nbsp;&nbsp;&nbsp;&nbsp;rescue MemoryOut
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;end
> > 
> > > &nbsp;&nbsp;&nbsp;&nbsp;open\_thr.join  
> > > end
> > > 
> > > This program seems OK and I can not find out the problem.
> > 
> > Add
> > 
> > Thread.abort\_on\_exception = true
> > 
> > at the top. That will help debugging.
> > 
> > If I add back the commented out line "mem\_thr.kill", then fds opened by
> > 
> > > ProcTable can not be closed, finally causes the error "too many opened  
> > > files".
> > > 
> > > Use the command "lsof" to check this, can see many files under /proc are  
> > > not closed.  
> > > If I comment out the kill again, everything goes well.
> > 
> > I'd say this is rather an issue with Sys::ProcTable than with Thread#kill:  
> > apparently that does not release resources properly under all  
> > circumstances. Maybe executing with strace helps to hunt this down.
> > 
> > Kind regards
> > 
> > robert
> > 
> > --  
> > [guy, jim, charlie].each {|him| remember.him do |as, often| as.you\_can -  
> > without end}  
> > [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)
