Projects

Ticket #664 (closed defect: fixed)

Opened 22 months ago

Last modified 14 months ago

MacRuby Crashes When Scheduling a Block to Run on the Main Thread from a Background Thread

Reported by: dylan@… Owned by: lsansonetti@…
Priority: blocker Milestone: MacRuby 0.8
Component: MacRuby Keywords: #reduction
Cc: nagachika00@…

Description (last modified by martinlagardette@…) (diff)

Code:

def main_thread( &block )
  block.performSelectorOnMainThread( 'call', withObject: nil, waitUntilDone: true )
end

Thread.new do 
  main_thread do 
    [1,2,3].each {|i| puts i }
  end
end

Expected result:

Output numbers to the console.

Actual result:

-Terminal-

$> macruby test.rb
Assertion failed: (errorcode == 0), function setInstance, file ThreadLocal.cpp, line 61.
Abort trap

-XCode (have to run the code twice for some reason, first time works) -

Assertion failed: ((b->flags & flags) == flags), function rb_vm_prepare_block, file dispatcher.cpp, line 1786.
Program received signal:  “SIGABRT”.

Backtrace (note that this was pasted into a ruby cocoa application and is triggered from a menu click):

#0  0x00007fff81b35fe6 in __kill ()
#1  0x00007fff81bd6e32 in abort ()
#2  0x00007fff81bc3e74 in __assert_rtn ()
#3  0x00000001001427e8 in rb_vm_prepare_block ()
#4  0x000000010115a149 in ?? ()
#5  0x0000000100149331 in rb_vm_block_eval ()
#6  0x00007fff87ddc647 in __NSThreadPerformPerform ()
#7  0x00007fff869c9271 in __CFRunLoopDoSources0 ()
#8  0x00007fff869c7469 in __CFRunLoopRun ()
#9  0x00007fff869c6c2f in CFRunLoopRunSpecific ()
#10 0x00007fff80ca5a75 in _NSUnhighlightCarbonMenu ()
#11 0x00007fff80f250b8 in -[NSMenu _internalPerformActionForItemAtIndex:] ()
#12 0x00007fff80dd79d5 in -[NSCarbonMenuImpl _carbonCommandProcessEvent:handlerCallRef:] ()
#13 0x00007fff80c84b60 in NSSLMMenuEventHandler ()
#14 0x00007fff886f1bd7 in DispatchEventToHandlers ()
#15 0x00007fff886f1126 in SendEventToEventTargetInternal ()
#16 0x00007fff8870ed49 in SendEventToEventTarget ()
#17 0x00007fff8873dd45 in SendHICommandEvent ()
#18 0x00007fff8876aa1a in SendMenuCommandWithContextAndModifiers ()
#19 0x00007fff8876a9d4 in SendMenuItemSelectedEvent ()
#20 0x00007fff8876a8dc in FinishMenuSelection ()
#21 0x00007fff8874bcf9 in MenuSelectCore ()
#22 0x00007fff8874b461 in _HandleMenuSelection2 ()
#23 0x00007fff80b55b79 in _NSHandleCarbonMenuEvent ()
#24 0x00007fff80b296a2 in _DPSNextEvent ()
#25 0x00007fff80b28b41 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#26 0x00007fff80aee747 in -[NSApplication run] ()
#27 0x00007fff80ae7468 in NSApplicationMain ()
#28 0x0000000101147870 in ?? ()
#29 0x000000010014c806 in rb_vm_dispatch ()
#30 0x00000001011263e4 in ?? ()
#31 0x000000010016115f in rb_vm_run ()
#32 0x00000001000462a9 in ruby_run_node ()
#33 0x00000001001614dc in macruby_main ()
#34 0x0000000100001d40 in main (argc=1, argv=0x7fff5fbff5f0) at
main.m:13

Macruby Version:

MacRuby version 0.6 (ruby 1.9.0) [universal-darwin10.0, x86_64] Nightly from 04/20/2010.

test.rb attached

Attachments

test.rb Download (188 bytes) - added by dylan@… 22 months ago.
simple test case

Change History

Changed 22 months ago by dylan@…

simple test case

  Changed 22 months ago by martinlagardette@…

  • description modified (diff)

follow-up: ↓ 3   Changed 22 months ago by lsansonetti@…

Proc#call is currently not directly callable from C/ObjC. Can you try this workaround instead:

def main_thread( &block )
  o = Object.new
  def o.call
    @block.call
  end
  o.instance_variable_set(:@block, block)
  o.performSelectorOnMainThread( 'call', withObject: nil, waitUntilDone: true )
end

Thread.new do
  main_thread do
    [1,2,3].each {|i| puts i }
  end
end

in reply to: ↑ 2   Changed 21 months ago by michael@…

Proc#call is currently not directly callable from C/ObjC. Can you try this workaround instead:

Just for your information, the workaround you described worked for me, Laurent. Glad I found it in Trac! I did not open this ticket though, so let's wait for the initiator's comment.

  Changed 21 months ago by dylan@…

Sorry for the delay on getting back to you. I finally ran this and got:

[11:21][Desktop]$ macruby test.rb Assertion failed: (errorcode == 0), function setInstance, file ThreadLocal.cpp, line 61. Abort trap [11:21][Desktop]$ macruby test.rb Assertion failed: (errorcode == 0), function setInstance, file ThreadLocal.cpp, line 61. Abort trap [11:22][Desktop]$ macruby test.rb [11:22][Desktop]$ macruby test.rb [11:22][Desktop]$

The first few times it fails, then runs with no output. This is with 0.6 final.

  Changed 21 months ago by dylan@…

Sorry, reformatting.

d[11:21][~]$ cd Desktop/
[11:21][Desktop]$ macruby test.rb
Assertion failed: (errorcode == 0), function setInstance, file ThreadLocal.cpp, line 61.
Abort trap
[11:21][Desktop]$ macruby test.rb
Assertion failed: (errorcode == 0), function setInstance, file ThreadLocal.cpp, line 61.
Abort trap
[11:22][Desktop]$ macruby test.rb
[11:22][Desktop]$ macruby test.rb
[11:22][Desktop]$ 

  Changed 21 months ago by martinlagardette@…

Could you try with a nightly instead of trunk? I can't seem to reproduce the problem with Laurent's code :-)

  Changed 21 months ago by lsansonetti@…

I think it's environmental (depends of your hardware). The bug is not fixed yet, afaik.

  Changed 21 months ago by nagachika00@…

  • cc nagachika00@… added

Cc Me!

  Changed 14 months ago by eloy.de.enige@…

  • keywords #reduction added

Still fails on trunk.

  Changed 14 months ago by lsansonetti@…

  • milestone set to MacRuby 1.0

The following snippet (my suggestion) works fine in trunk.

framework 'Cocoa'

NSApplication.sharedApplication

def main_thread( &block )
  o = Object.new
  def o.call
    @block.call
  end
  o.instance_variable_set(:@block, block)
  o.performSelectorOnMainThread( 'call', withObject: nil, waitUntilDone: true )
end

Thread.new do
  main_thread do
    [1,2,3].each {|i| puts i }
  end
end

NSApp.run

The original doesn't, as ObjC is not able to perform selectors defined in MacRuby Core (in C), such as Proc#call. We should try to do something in 1.0.

  Changed 14 months ago by lsansonetti@…

  • status changed from new to closed
  • resolution set to fixed
  • milestone changed from MacRuby 1.0 to MacRuby 0.8

Should be fixed in r4987.

$ cat t2.rb 
framework 'Cocoa'

NSApplication.sharedApplication

def main_thread( &block )
  block.performSelectorOnMainThread( 'call', withObject: nil, waitUntilDone: true )
end

Thread.new do 
  main_thread do 
    [1,2,3].each {|i| puts i }
  end
end

NSApp.run

$ ./miniruby t2.rb 
1
2
3
^C
Note: See TracTickets for help on using tickets.