The spec says that a 'return' from a thread should raise a LocalJumpError. Looking at the code for RETURN_NODE in compiler.cpp, the question of "Is this a thread" is never asked. And, I guess this exception is only for the top level block of the thread since a function called from the block could do a return. I looked briefly at the Thread create process and I didn't see anything that flagged the block passed as the top level block for the thread. The testcase causes a segmentation fault. I looked at the signal handler too and it appears as if it is "lets do this for now and address it later" code. The SEGV fault handler simply sets a flag and returns. The return will put us back where we were just at so we immediately seg fault again and then we do an exit -- with no core file. I don't see the value of catching SEGV in the first place unless the underlying Ruby code has asked us to do that. I think that would generally apply to all signals. Perry
Hi Perry, Which spec are you talking about specifically? Laurent On Jul 9, 2009, at 5:56 AM, Perry Smith wrote:
The spec says that a 'return' from a thread should raise a LocalJumpError.
Looking at the code for RETURN_NODE in compiler.cpp, the question of "Is this a thread" is never asked. And, I guess this exception is only for the top level block of the thread since a function called from the block could do a return.
I looked briefly at the Thread create process and I didn't see anything that flagged the block passed as the top level block for the thread.
The testcase causes a segmentation fault. I looked at the signal handler too and it appears as if it is "lets do this for now and address it later" code. The SEGV fault handler simply sets a flag and returns. The return will put us back where we were just at so we immediately seg fault again and then we do an exit -- with no core file.
I don't see the value of catching SEGV in the first place unless the underlying Ruby code has asked us to do that. I think that would generally apply to all signals.
Perry
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
The file is: ./spec/frozen/language/return_spec.rb I don't know how to describe which one other than the first describe that starts "in a Thread" Currently it does: The return keyword in a Thread - raises a LocalJumpError if used to exit a threadSEGV recieved in SEGV handler unknown: [BUG] Segmentation fault Perry Ease Software, Inc. ( http://www.easesoftware.com ) Low cost SATA Disk Systems for IBMs p5, pSeries, and RS/6000 AIX systems On Jul 9, 2009, at 2:35 PM, Laurent Sansonetti wrote:
Hi Perry,
Which spec are you talking about specifically?
Laurent
On Jul 9, 2009, at 5:56 AM, Perry Smith wrote:
The spec says that a 'return' from a thread should raise a LocalJumpError.
Looking at the code for RETURN_NODE in compiler.cpp, the question of "Is this a thread" is never asked. And, I guess this exception is only for the top level block of the thread since a function called from the block could do a return.
I looked briefly at the Thread create process and I didn't see anything that flagged the block passed as the top level block for the thread.
The testcase causes a segmentation fault. I looked at the signal handler too and it appears as if it is "lets do this for now and address it later" code. The SEGV fault handler simply sets a flag and returns. The return will put us back where we were just at so we immediately seg fault again and then we do an exit -- with no core file.
I don't see the value of catching SEGV in the first place unless the underlying Ruby code has asked us to do that. I think that would generally apply to all signals.
Perry
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
I was planning to rewrite return-from-a-block today (or maybe tomorrow). The current SjLj-based implementation is not correct because it does not call ensure blocks, so I was thinking of using a specialized C++ exception instead, which should do the trick. # This was a long-standing issue but yesterday night I found a use case where it's problematic: Mutex#synchronize won't unlock if return is called from it. Normally with the new implementation we should be able to catch the specialized exception inside rb_vm_thread_run() and appropriately raise a LocalJumpError. Thanks for your preliminary investigation on this! Laurent On Jul 9, 2009, at 12:43 PM, Perry Smith wrote:
The file is: ./spec/frozen/language/return_spec.rb
I don't know how to describe which one other than the first describe that starts "in a Thread"
Currently it does:
The return keyword in a Thread - raises a LocalJumpError if used to exit a threadSEGV recieved in SEGV handler unknown: [BUG] Segmentation fault
Perry Ease Software, Inc. ( http://www.easesoftware.com )
Low cost SATA Disk Systems for IBMs p5, pSeries, and RS/6000 AIX systems
On Jul 9, 2009, at 2:35 PM, Laurent Sansonetti wrote:
Hi Perry,
Which spec are you talking about specifically?
Laurent
On Jul 9, 2009, at 5:56 AM, Perry Smith wrote:
The spec says that a 'return' from a thread should raise a LocalJumpError.
Looking at the code for RETURN_NODE in compiler.cpp, the question of "Is this a thread" is never asked. And, I guess this exception is only for the top level block of the thread since a function called from the block could do a return.
I looked briefly at the Thread create process and I didn't see anything that flagged the block passed as the top level block for the thread.
The testcase causes a segmentation fault. I looked at the signal handler too and it appears as if it is "lets do this for now and address it later" code. The SEGV fault handler simply sets a flag and returns. The return will put us back where we were just at so we immediately seg fault again and then we do an exit -- with no core file.
I don't see the value of catching SEGV in the first place unless the underlying Ruby code has asked us to do that. I think that would generally apply to all signals.
Perry
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
I've been studiously avoiding doing thread programming, but I realize that it's needed for some kinds of problems. Anyway, reading the thread thread made me wonder whether Laurent's new and improved threads will be compatible with other Ruby thread implementations or whether (say) some modifications may be needed to existing code. More generally, as we learn about how MacRuby varies from other Rubies, we should document this lore in a wiki page: Better isn't always better, but better is always different. If folks want to propose content for the page, I'm willing to create and maintain it... -r -- http://www.cfcl.com/rdm Rich Morin http://www.cfcl.com/rdm/resume rdm@cfcl.com http://www.cfcl.com/rdm/weblog +1 650-873-7841 Technical editing and writing, programming, and web development
I think Laurent will write specific MacRuby specs for these differences, so you could look it up from there and write the wiki. Or others interested could simply check the specs to see it for themselves. Eloy On Jul 9, 2009, at 10:12 PM, Rich Morin wrote:
I've been studiously avoiding doing thread programming, but I realize that it's needed for some kinds of problems. Anyway, reading the thread thread made me wonder whether Laurent's new and improved threads will be compatible with other Ruby thread implementations or whether (say) some modifications may be needed to existing code.
More generally, as we learn about how MacRuby varies from other Rubies, we should document this lore in a wiki page:
Better isn't always better, but better is always different.
If folks want to propose content for the page, I'm willing to create and maintain it...
-r -- http://www.cfcl.com/rdm Rich Morin http://www.cfcl.com/rdm/resume rdm@cfcl.com http://www.cfcl.com/rdm/weblog +1 650-873-7841
Technical editing and writing, programming, and web development _______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
Hi Laurent, You used the term "block" below. I don't know enough about the code yet but I would assume that "block" means either a basic block or something between curly braces. Those entities do not have "ensure" -- (oh, gee, you used the term block here too...) Anyway. My thought / suggestions / question is perhaps making the things between curly braces simple and the things between "begin" and "end" (which can have ensure statements) more complex. The point is that curly braces come up much more often and keeping them simple and fast would be nice. I'm also worried that the use of exceptions to implement often used paths like "return" may be very expensive. Depending upon the implementation, exceptions can cost 0 for the non-exception case but the processing of an actually exception is very expensive. It would be nice if that cost would only be incurred in very rare cases. On Jul 9, 2009, at 2:50 PM, Laurent Sansonetti wrote:
I was planning to rewrite return-from-a-block today (or maybe tomorrow). The current SjLj-based implementation is not correct because it does not call ensure blocks, so I was thinking of using a specialized C++ exception instead, which should do the trick.
# This was a long-standing issue but yesterday night I found a use case where it's problematic: Mutex#synchronize won't unlock if return is called from it.
Normally with the new implementation we should be able to catch the specialized exception inside rb_vm_thread_run() and appropriately raise a LocalJumpError.
Thanks for your preliminary investigation on this!
Laurent
On Jul 9, 2009, at 12:43 PM, Perry Smith wrote:
The file is: ./spec/frozen/language/return_spec.rb
I don't know how to describe which one other than the first describe that starts "in a Thread"
Currently it does:
The return keyword in a Thread - raises a LocalJumpError if used to exit a threadSEGV recieved in SEGV handler unknown: [BUG] Segmentation fault
Perry Ease Software, Inc. ( http://www.easesoftware.com )
Low cost SATA Disk Systems for IBMs p5, pSeries, and RS/6000 AIX systems
On Jul 9, 2009, at 2:35 PM, Laurent Sansonetti wrote:
Hi Perry,
Which spec are you talking about specifically?
Laurent
On Jul 9, 2009, at 5:56 AM, Perry Smith wrote:
The spec says that a 'return' from a thread should raise a LocalJumpError.
Looking at the code for RETURN_NODE in compiler.cpp, the question of "Is this a thread" is never asked. And, I guess this exception is only for the top level block of the thread since a function called from the block could do a return.
I looked briefly at the Thread create process and I didn't see anything that flagged the block passed as the top level block for the thread.
The testcase causes a segmentation fault. I looked at the signal handler too and it appears as if it is "lets do this for now and address it later" code. The SEGV fault handler simply sets a flag and returns. The return will put us back where we were just at so we immediately seg fault again and then we do an exit -- with no core file.
I don't see the value of catching SEGV in the first place unless the underlying Ruby code has asked us to do that. I think that would generally apply to all signals.
Perry
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
Hi Perry, On Jul 10, 2009, at 5:14 AM, Perry Smith wrote:
Hi Laurent,
You used the term "block" below. I don't know enough about the code yet but I would assume that "block" means either a basic block or something between curly braces. Those entities do not have "ensure" -- (oh, gee, you used the term block here too...) Anyway. My thought / suggestions / question is perhaps making the things between curly braces simple and the things between "begin" and "end" (which can have ensure statements) more complex. The point is that curly braces come up much more often and keeping them simple and fast would be nice.
In MacRuby, a rb_vm_block_t structure represents a Ruby block. 1.times { p 42 } # a block FIle.open(path) { |io. } # a block # not a block begin foo rescue end p = proc { p 42 } # a block, transformed into a Proc The current implementation tries to make blocks as fast and simple as possible (considering that we need to support the Ruby standards). If you have any performance suggestion let us know.
I'm also worried that the use of exceptions to implement often used paths like "return" may be very expensive. Depending upon the implementation, exceptions can cost 0 for the non-exception case but the processing of an actually exception is very expensive. It would be nice if that cost would only be incurred in very rare cases.
Indeed, raising an exception is very slow for us since we use C++ exceptions, but it's only used in exceptional cases, or in very explicit use cases like returning from a block (the other return statements don't use an exception). Also the new runtime in the upcoming version of Mac OS X seems to be faster. Laurent
On Jul 9, 2009, at 2:50 PM, Laurent Sansonetti wrote:
I was planning to rewrite return-from-a-block today (or maybe tomorrow). The current SjLj-based implementation is not correct because it does not call ensure blocks, so I was thinking of using a specialized C++ exception instead, which should do the trick.
# This was a long-standing issue but yesterday night I found a use case where it's problematic: Mutex#synchronize won't unlock if return is called from it.
Normally with the new implementation we should be able to catch the specialized exception inside rb_vm_thread_run() and appropriately raise a LocalJumpError.
Thanks for your preliminary investigation on this!
Laurent
On Jul 9, 2009, at 12:43 PM, Perry Smith wrote:
The file is: ./spec/frozen/language/return_spec.rb
I don't know how to describe which one other than the first describe that starts "in a Thread"
Currently it does:
The return keyword in a Thread - raises a LocalJumpError if used to exit a threadSEGV recieved in SEGV handler unknown: [BUG] Segmentation fault
Perry Ease Software, Inc. ( http://www.easesoftware.com )
Low cost SATA Disk Systems for IBMs p5, pSeries, and RS/6000 AIX systems
On Jul 9, 2009, at 2:35 PM, Laurent Sansonetti wrote:
Hi Perry,
Which spec are you talking about specifically?
Laurent
On Jul 9, 2009, at 5:56 AM, Perry Smith wrote:
The spec says that a 'return' from a thread should raise a LocalJumpError.
Looking at the code for RETURN_NODE in compiler.cpp, the question of "Is this a thread" is never asked. And, I guess this exception is only for the top level block of the thread since a function called from the block could do a return.
I looked briefly at the Thread create process and I didn't see anything that flagged the block passed as the top level block for the thread.
The testcase causes a segmentation fault. I looked at the signal handler too and it appears as if it is "lets do this for now and address it later" code. The SEGV fault handler simply sets a flag and returns. The return will put us back where we were just at so we immediately seg fault again and then we do an exit -- with no core file.
I don't see the value of catching SEGV in the first place unless the underlying Ruby code has asked us to do that. I think that would generally apply to all signals.
Perry
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
On Jul 10, 2009, at 1:58 PM, Laurent Sansonetti wrote:
Indeed, raising an exception is very slow for us since we use C++ exceptions, but it's only used in exceptional cases, or in very explicit use cases like returning from a block (the other return statements don't use an exception). Also the new runtime in the upcoming version of Mac OS X seems to be faster.
I'm not sure we are both on the same page yet. In your examples: 1.times { p 42 } after the "p 42" there is a return. Perhaps not a return statement but a return. Also, there is no ensure and no way to put an ensure in without a "begin / end" pair. So, what I'm suggesting is to make: begin foo return here rescue dog end be the special case. Not: 1.times { return 18 } I'm guessing that is what you are doing but I wasn't sure. Perry
On Jul 10, 2009, at 12:44 PM, Perry Smith wrote:
On Jul 10, 2009, at 1:58 PM, Laurent Sansonetti wrote:
Indeed, raising an exception is very slow for us since we use C++ exceptions, but it's only used in exceptional cases, or in very explicit use cases like returning from a block (the other return statements don't use an exception). Also the new runtime in the upcoming version of Mac OS X seems to be faster.
I'm not sure we are both on the same page yet.
In your examples:
1.times { p 42 }
after the "p 42" there is a return. Perhaps not a return statement but a return. Also, there is no ensure and no way to put an ensure in without a "begin / end" pair.
In this example there is obviously no return statement, so it will be cheap. The block value or the break statement don't use this mechanism.
So, what I'm suggesting is to make:
begin foo return here rescue dog end
be the special case. Not:
1.times { return 18 }
I'm guessing that is what you are doing but I wasn't sure.
What about the following: def foo 1.times { return 42 } p :nok end foo In this case, you need a way to return the current method from the block to not execute the "p :nok" expression. Unwinding the stack is a way to implement this. Now, consider: def foo begin yield ensure p :ok end end def bar foo { return 42 } end p bar Here you don't have a choice, since you need to honor the ensure block. In Ruby, return is semantically similar to an exception in some cases. This is unfortunate :-) Laurent
On Fri, Jul 10, 2009 at 3:02 PM, Laurent Sansonetti<lsansonetti@apple.com> wrote:
Now, consider:
def foo begin yield ensure p :ok end end def bar foo { return 42 } end p bar
Here you don't have a choice, since you need to honor the ensure block.
In Ruby, return is semantically similar to an exception in some cases. This is unfortunate :-)
Return isn't really an exception, since you can't catch/rescue it. The issue here is that ensure blocks are a hard requirement, and they must fire even if a non-local return unrolls through them. The return here doesn't necessarily need to be implemented as an exception, but it does need to fire ensure blocks. In JRuby, we do use an exception, but we don't have any other way of unrolling the stack. - Charlie
participants (5)
-
Charles Oliver Nutter
-
Eloy Duran
-
Laurent Sansonetti
-
Perry Smith
-
Rich Morin