Bug #2488

thread usage can result in bad HANDLE

Added by Roger Pack about 5 years ago. Updated almost 4 years ago.

[ruby-core:27199]
Status:Closed
Priority:Normal
Assignee:Koichi Sasada
ruby -v:ruby 1.9.2dev (2009-12-31 trunk 26205) [i386-mswin32] Backport:

Description

=begin
require 'thwait'
loop {
a = []
10.times { a << Thread.new {}}
ThreadsWait.all_waits(a)
print '.'
}

C:\dev\digitalarchive_trunk>ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-mingw32]

C:\dev\digitalarchive_trunk>ruby stress_th.rb
.............[BUG] The handle is invalid.

ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-mingw32]

-- control frame ----------


-- Ruby level backtrace information-----------------------------------------

[NOTE]
You may encounter a bug of Ruby interpreter. Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Works fine with 1.9.2

Thanks.
-r
=end

lock_before_reset.patch Magnifier (1.22 KB) _ wanabe, 05/01/2010 09:24 PM

History

#1 Updated by Usaku NAKAMURA about 5 years ago

  • Assignee set to Usaku NAKAMURA
  • Target version set to 2.0.0

=begin
can reproduce with trunk.
=end

#2 Updated by Usaku NAKAMURA about 5 years ago

  • Status changed from Open to Assigned
  • ruby -v set to ruby 1.9.2dev (2009-12-31 trunk 26205) [i386-mswin32]

=begin

=end

#3 Updated by Usaku NAKAMURA about 5 years ago

  • Category set to core
  • Assignee changed from Usaku NAKAMURA to Koichi Sasada

=begin

=end

#4 Updated by Roger Pack almost 5 years ago

=begin
appears "better" in trunk but not totally fixed, with this version:

ruby 1.9.2dev (2010-04-09 trunk 27265) [i386-mingw32]
=end

#5 Updated by Roger Pack almost 5 years ago

=begin
from 3183 this code crashes trunk reliably still:

loop {
all = []
700.times{|i|
all << Thread.new{}
puts i
}
all.each(&:join)
}

=end

#6 Updated by Luis Lavena almost 5 years ago

=begin
Roger,

Running r27453 over here, cannot make your example crash (based on bug report #3183).

OS: Windows 7, x64, 4GB RAM

=end

#7 Updated by _ wanabe almost 5 years ago

=begin
Roger,
Does this patch fix the issue?

Developers (especially Koichi),
Is this solution right?
(Using GVL, timing of lock, condition, etc.)
=end

#8 Updated by Roger Pack almost 5 years ago

=begin
That patch seems to fix it for me.

@Luis: I am able to reproduce #3183 (sometimes it takes a few minutes, and requires the puts in there). Ex backtrace:

[BUG] w32_reset_event: The handle is invalid.

ruby 1.9.2dev (2010-05-05 trunk 27620) [i386-mingw32]

-- control frame ----------


[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

(Windows 7 32 bit, 4GB RAM). I assume it's just a timing issue.

-rp
=end

#9 Updated by Usaku NAKAMURA almost 5 years ago

=begin
Hello,

In message " [Bug #2488] thread usage can result in bad HANDLE"
on May.05,2010 06:35:12, redmine@ruby-lang.org wrote:
| (Windows 7 32 bit, 4GB RAM). I assume it's just a timing issue.

I think so, too.
wanabe-san, please check in the patch and close #2488 and #3183.

Regards
--
U.Nakamura usa@garbagecollect.jp

=end

#10 Updated by _ wanabe almost 5 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r27630.
Roger, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

#11 Updated by _ wanabe almost 5 years ago

=begin
Hello,

2010/5/6, Caleb Clausen vikkous@gmail.com:

I don't understand win32 programming that well...

Me too.

Why is it necessary to re-check that intr is set to what it was set to
just two lines before? I assume it might be changed by the action of
another thread, but if that's the case, wouldn't it be better to just
check that field once while inside the global_vm_lock? (ie move the
lock/unlock to be around the whole if statement.)

Yes, you are right.
I think first that it is good to avoid native_mutex_lock() as much as possible.
Now, I realize the condition (th && !intr) is fulfilled in a only few moments.

But if we delete check of outside, new check of mutex's existence will
be needed.
I'm afraid that it doesn't make sense from the standpoint of cost down.

For that matter, shouldn't ruby be using the api provided by windows
(WaitForSingleObject, apparently) to check the state of this 'event
object' (really a semaphore)? If you do it that way, then maybe the
global_vm_lock doesn't need to be touched.

I guess it is not very good idea.
Because th->native_thread_data.interrupt_event can be destroyed
by native_thread_destroy() between check and lock, but GVL can't.

And if ruby use 'event object', we should insert locking to somewhere
such as thread_cleanup_func(), but lock with GVL is in thread_start_func_2()
already. There is not a new cost.

But if you know the use case the lock can be harm, I'm glad to change it.

--
wanabe

=end

Also available in: Atom PDF