Some OpenGL sample code
Hello to everyone, I tried to port two OpenGL sample code examples from the ADC in MacRuby ( and plan to port some more ). You can find both projects here : http://github.com/sojastar Both kind of work but have problems I can't find solutions to so I turn to the list for a little help. One of the examples ( MacRuby-BoingX ) randomly crashes, either on launch or exit, about one time out of five. When launching the application from XCode, I get : Program received signal: “EXC_BAD_ACCESS”. which suggests a memory access error. It is not unlikely since the OpenGL functions use a lot of pointers. I am trying to use DTrace to identify the problem but it is very new territory for me. I wrote a script returning the name of the last function called. I get a different result for every crash. I imagine part of my data ( most often, the vertex data ) must be corrupted, and maybe from the various pointer operations I have to do to use OpenGL. Has anyone any suggestion on how I could troubleshoot such a problem ? The problem with the second example is directly related to pointers. The function CGLQueryRendererInfo function expects a pointer to a CGLRendererInfoObj object as its second argument. After the call, the pointer points to a valid CGLRendererInfoObj object. So I did something like this : renderer_info = Pointer.new_with_type("^{_CGLRendererInfoObj}") renderer_error = CGLQueryRendererInfo(display_mask, renderer_info, renderer_count) and get : expected instance of Pointer of type `^{_CGLRendererInfoObject}', got `^{_CGLRendererInfoObj}' (TypeError) If I change the pointer type to '^{_CGLRendererInfoObject}', CGLQueryRendererInfo doesn't complain anymore, but all other following functions using the CGLRendererInfoObj do. Could this be a bridge support problem ? As anyone who has a better background in Cocoa any idea ? I know some things should be done in bundles but, for sample code, I thought it would be good to try to go Ruby all the way. My configuration : Intel Core 2 Duo MacBook Pro, Mac OS 10.6.2, MacRuby 0.5b2 Thanks, Julien Jassaud
Bonjour Julien, On Dec 18, 2009, at 4:54 AM, Julien Jassaud wrote:
Hello to everyone,
I tried to port two OpenGL sample code examples from the ADC in MacRuby ( and plan to port some more ). You can find both projects here : http://github.com/sojastar
Awesome! I would love to ship these as part of the MacRuby samples once they are completed :)
Both kind of work but have problems I can't find solutions to so I turn to the list for a little help.
One of the examples ( MacRuby-BoingX ) randomly crashes, either on launch or exit, about one time out of five. When launching the application from XCode, I get :
Program received signal: “EXC_BAD_ACCESS”.
which suggests a memory access error. It is not unlikely since the OpenGL functions use a lot of pointers. I am trying to use DTrace to identify the problem but it is very new territory for me. I wrote a script returning the name of the last function called. I get a different result for every crash. I imagine part of my data ( most often, the vertex data ) must be corrupted, and maybe from the various pointer operations I have to do to use OpenGL. Has anyone any suggestion on how I could troubleshoot such a problem ?
I would start by getting the full backtrace from the debugger and examine it. Most of the time it is easy to find what's wrong. Could you enter "thread apply all bt" into the debugger shell and paste us the result? If the crash is random there is a possibility that it might be related to garbage collection. A good way to know for sure is to disable it, by setting the GC_DISABLE environment variable to any value before starting the application.
The problem with the second example is directly related to pointers. The function CGLQueryRendererInfo function expects a pointer to a CGLRendererInfoObj object as its second argument. After the call, the pointer points to a valid CGLRendererInfoObj object. So I did something like this :
renderer_info = Pointer.new_with_type("^{_CGLRendererInfoObj}") renderer_error = CGLQueryRendererInfo(display_mask, renderer_info, renderer_count)
and get :
expected instance of Pointer of type `^{_CGLRendererInfoObject}', got `^{_CGLRendererInfoObj}' (TypeError)
If I change the pointer type to '^{_CGLRendererInfoObject}', CGLQueryRendererInfo doesn't complain anymore, but all other following functions using the CGLRendererInfoObj do. Could this be a bridge support problem ? As anyone who has a better background in Cocoa any idea ? I know some things should be done in bundles but, for sample code, I thought it would be good to try to go Ruby all the way.
I'm not familiar with OpenGL but it might be a BridgeSupport problem... What other functions using the CGLRendererInfoObj are failing? It might be good to reduce this problem to a small script (even if it can be hard, because of OpenGL). Laurent
Bonjour Laurent :)
Awesome! I would love to ship these as part of the MacRuby samples once they are completed :)
Soon, hopefully !
Could you enter "thread apply all bt" into the debugger shell and paste us the result?
Here it is. I don't understand much. The only information I can add is that thread 4 do not systematically appear. Besides that, the backtraces are consistent. Thread 4 (process 37173): #0 0x00007fff826119da in __workq_kernreturn () #1 0x00007fff82611dec in _pthread_wqthread () #2 0x00007fff82611a55 in start_wqthread () Thread 3 (process 37173): #0 0x00007fff826119da in __workq_kernreturn () #1 0x00007fff82611dec in _pthread_wqthread () #2 0x00007fff82611a55 in start_wqthread () Thread 2 (process 37173): #0 0x00007fff82610bba in kevent () #1 0x00007fff82612a85 in _dispatch_mgr_invoke () #2 0x00007fff8261275c in _dispatch_queue_invoke () #3 0x00007fff82612286 in _dispatch_worker_thread2 () #4 0x00007fff82611bb8 in _pthread_wqthread () #5 0x00007fff82611a55 in start_wqthread () Thread 1 (process 37173): #0 0x00007fff87e7011c in objc_msgSend () #1 0x00007fff802332b0 in -[NSCarbonMenuImpl _carbonMenuInsertItem:atCarbonIndex:] () #2 0x00007fff80393f5b in -[NSCarbonMenuImpl _privatePopulateCarbonMenu] () #3 0x00007fff80393d77 in -[NSCarbonMenuImpl _carbonPopulateEvent:handlerCallRef:] () #4 0x00007fff80393b60 in NSSLMMenuEventHandler () #5 0x00007fff86032bd7 in DispatchEventToHandlers () #6 0x00007fff86032126 in SendEventToEventTargetInternal () #7 0x00007fff86031f97 in SendEventToEventTargetWithOptions () #8 0x00007fff86073e2d in SendMenuPopulate () #9 0x00007fff86073c6e in PopulateMenu () #10 0x00007fff860732fe in Check1MenuForKeyEvent () #11 0x00007fff86072a08 in CheckMenusForKeyEvent () #12 0x00007fff86072644 in _IsMenuKeyEvent () #13 0x00007fff8607236a in IsMenuKeyEvent () #14 0x00007fff80393914 in -[NSCarbonMenuImpl _menuItemWithKeyEquivalentMatchingEventRef:] () #15 0x00007fff803936cb in _NSFindMenuItemMatchingCommandKeyEvent () #16 0x00007fff80264c35 in _NSHandleCarbonMenuEvent () #17 0x00007fff802386a2 in _DPSNextEvent () #18 0x00007fff80237b41 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] () #19 0x00007fff801fd747 in -[NSApplication run] () #20 0x00007fff801f6468 in NSApplicationMain () #21 0x0000000101d09770 in ?? () #22 0x0000000101d00314 in ?? () #23 0x0000000100040ff9 in ruby_run_node () #24 0x0000000100179769 in macruby_main () #25 0x0000000100000e70 in main ()
If the crash is random there is a possibility that it might be related to garbage collection. A good way to know for sure is to disable it, by setting the GC_DISABLE environment variable to any value before starting the application.
Indeed, after : macbook-de-julien-jassaud-2:Debug sojastar$ export GC_DISABLE=1 the application doesn't seem to crash anymore. But what should I do now ?
I'm not familiar with OpenGL but it might be a BridgeSupport problem... What other functions using the CGLRendererInfoObj are failing?
Sorry, when I said all other functions, I really meant all other calls to CGLDescribeRenderer. After a series of call to CGLDescribeRenderer, the CGLRendererInfoObj is destroyed by CGLDestroyRendererInfo. If I bypass this whole section of code, I get more problems with blablablaObj and sameblablablaObject pointer confusion. The documentation for those types mentions only CGLRendererInfoObj, CGLPixelFormatObj or CGLContextObj, though
It might be good to reduce this problem to a small script (even if it can be hard, because of OpenGL).
I created a small project illustrating the problem. You can find it here : http://github.com/sojastar/Some-MacRuby-sample-code/tree/master/buggy/ The problem starts at line 85 of file MyOpenGLView.rb. I also had a problem with function NSBitmapImageRep. Again, a pointer problem. Having an NSBitmapImageRep, the function bitmapData returns an (unsigned char *) but in MacRuby, it returns an empty string. The workaround was to create the class in an Objective C bundle. Many thanks for your very prompt answer. Julien
Salut Julien, On Dec 19, 2009, at 12:17 AM, Julien Jassaud wrote:
Bonjour Laurent :)
Awesome! I would love to ship these as part of the MacRuby samples once they are completed :)
Soon, hopefully !
Could you enter "thread apply all bt" into the debugger shell and paste us the result?
Here it is. I don't understand much. The only information I can add is that thread 4 do not systematically appear. Besides that, the backtraces are consistent. [...]
I looked at your project and I was able to reproduce the crashes, which smelled like memory smashers. Then, looking at the code, I saw bad usage of the Pointer class. An example: @light_position = Pointer.new_with_type('f') @light_position[0] = -2.0 @light_position[1] = 2.0 @light_position[2] = 1.0 @light_position[3] = 0.0 This is not good, because this creates a pointer to a float of 1 element (exactly like malloc(sizeof(float)) in C) but then you set objects to indexes (1, 2, 3) out of the pointer's bounds. The correct code should be: @light_position = Pointer.new_with_type('f', 4) @light_position[0] = -2.0 @light_position[1] = 2.0 @light_position[2] = 1.0 @light_position[3] = 0.0 The second argument allows you to specify the number of elements the Pointer will hold (by default, it's 1). As in C, it's very easy to corrupt memory or crash the program. Sometimes we get pointers from C or Objective-C, we wrap them inside Pointer objects and we do not know the number of elements, but in this case, when the Pointer is constructed by Ruby itself, I believe MacRuby should not let you do this and appropriately raise an exception. I will fix that ASAP. The random crashes may perhaps disappear after you fix the code.
If the crash is random there is a possibility that it might be related to garbage collection. A good way to know for sure is to disable it, by setting the GC_DISABLE environment variable to any value before starting the application.
Indeed, after :
macbook-de-julien-jassaud-2:Debug sojastar$ export GC_DISABLE=1
the application doesn't seem to crash anymore. But what should I do now ?
I'm not familiar with OpenGL but it might be a BridgeSupport problem... What other functions using the CGLRendererInfoObj are failing?
Sorry, when I said all other functions, I really meant all other calls to CGLDescribeRenderer. After a series of call to CGLDescribeRenderer, the CGLRendererInfoObj is destroyed by CGLDestroyRendererInfo.
If I bypass this whole section of code, I get more problems with blablablaObj and sameblablablaObject pointer confusion. The documentation for those types mentions only CGLRendererInfoObj, CGLPixelFormatObj or CGLContextObj, though
It might be good to reduce this problem to a small script (even if it can be hard, because of OpenGL).
I created a small project illustrating the problem. You can find it here : http://github.com/sojastar/Some-MacRuby-sample-code/tree/master/buggy/ The problem starts at line 85 of file MyOpenGLView.rb.
I also had a problem with function NSBitmapImageRep. Again, a pointer problem. Having an NSBitmapImageRep, the function bitmapData returns an (unsigned char *) but in MacRuby, it returns an empty string. The workaround was to create the class in an Objective C bundle.
Thanks, I reproduce the problem here too. Could you file a ticket on Trac, this way we won't forget to fix it? Bonnes fêtes! Laurent
Laurent,
Could you enter "thread apply all bt" into the debugger shell and paste us the result?
Here it is. I don't understand much. The only information I can add is that thread 4 do not systematically appear. Besides that, the backtraces are consistent. [...]
I looked at your project and I was able to reproduce the crashes, which smelled like memory smashers. Then, looking at the code, I saw bad usage of the Pointer class.
An example:
@light_position = Pointer.new_with_type('f') @light_position[0] = -2.0 @light_position[1] = 2.0 @light_position[2] = 1.0 @light_position[3] = 0.0
This is not good, because this creates a pointer to a float of 1 element (exactly like malloc(sizeof(float)) in C) but then you set objects to indexes (1, 2, 3) out of the pointer's bounds.
The correct code should be:
@light_position = Pointer.new_with_type('f', 4) @light_position[0] = -2.0 @light_position[1] = 2.0 @light_position[2] = 1.0 @light_position[3] = 0.0
The second argument allows you to specify the number of elements the Pointer will hold (by default, it's 1).
As in C, it's very easy to corrupt memory or crash the program. Sometimes we get pointers from C or Objective-C, we wrap them inside Pointer objects and we do not know the number of elements, but in this case, when the Pointer is constructed by Ruby itself, I believe MacRuby should not let you do this and appropriately raise an exception. I will fix that ASAP.
The random crashes may perhaps disappear after you fix the code.
Sorry. I should have read the source for the Pointer class. The crashes are gone.
I'm not familiar with OpenGL but it might be a BridgeSupport problem... What other functions using the CGLRendererInfoObj are failing?
Sorry, when I said all other functions, I really meant all other calls to CGLDescribeRenderer. After a series of call to CGLDescribeRenderer, the CGLRendererInfoObj is destroyed by CGLDestroyRendererInfo.
If I bypass this whole section of code, I get more problems with blablablaObj and sameblablablaObject pointer confusion. The documentation for those types mentions only CGLRendererInfoObj, CGLPixelFormatObj or CGLContextObj, though
Thanks, I reproduce the problem here too. Could you file a ticket on Trac, this way we won't forget to fix it?
Done. Thanks. Bonnes fêtes également ! Julien
The first thing I did to learn Macruby was to port the Ruby Rocks tutorial (http://www.rubycocoa.com/ruby-rocks). It is here if anyone is interested: http://www.lastobelus.com/uncategorized/ruby-rocks-ported-to-macruby (I kept playing for a while after finishing the tutorial, so my version has more code than the tutorial does). Feel free to put this on the samples page as well. Cheerio, Michael Johnston lastobelus@mac.com On 18-Dec-09, at 2:41 PM, Laurent Sansonetti wrote:
Bonjour Julien,
On Dec 18, 2009, at 4:54 AM, Julien Jassaud wrote:
Hello to everyone,
I tried to port two OpenGL sample code examples from the ADC in MacRuby ( and plan to port some more ). You can find both projects here : http://github.com/sojastar
Awesome! I would love to ship these as part of the MacRuby samples once they are completed :)
Both kind of work but have problems I can't find solutions to so I turn to the list for a little help.
One of the examples ( MacRuby-BoingX ) randomly crashes, either on launch or exit, about one time out of five. When launching the application from XCode, I get :
Program received signal: “EXC_BAD_ACCESS”.
which suggests a memory access error. It is not unlikely since the OpenGL functions use a lot of pointers. I am trying to use DTrace to identify the problem but it is very new territory for me. I wrote a script returning the name of the last function called. I get a different result for every crash. I imagine part of my data ( most often, the vertex data ) must be corrupted, and maybe from the various pointer operations I have to do to use OpenGL. Has anyone any suggestion on how I could troubleshoot such a problem ?
I would start by getting the full backtrace from the debugger and examine it. Most of the time it is easy to find what's wrong.
Could you enter "thread apply all bt" into the debugger shell and paste us the result?
If the crash is random there is a possibility that it might be related to garbage collection. A good way to know for sure is to disable it, by setting the GC_DISABLE environment variable to any value before starting the application.
The problem with the second example is directly related to pointers. The function CGLQueryRendererInfo function expects a pointer to a CGLRendererInfoObj object as its second argument. After the call, the pointer points to a valid CGLRendererInfoObj object. So I did something like this :
renderer_info = Pointer.new_with_type("^{_CGLRendererInfoObj}") renderer_error = CGLQueryRendererInfo(display_mask, renderer_info, renderer_count)
and get :
expected instance of Pointer of type `^{_CGLRendererInfoObject}', got `^{_CGLRendererInfoObj}' (TypeError)
If I change the pointer type to '^{_CGLRendererInfoObject}', CGLQueryRendererInfo doesn't complain anymore, but all other following functions using the CGLRendererInfoObj do. Could this be a bridge support problem ? As anyone who has a better background in Cocoa any idea ? I know some things should be done in bundles but, for sample code, I thought it would be good to try to go Ruby all the way.
I'm not familiar with OpenGL but it might be a BridgeSupport problem... What other functions using the CGLRendererInfoObj are failing? It might be good to reduce this problem to a small script (even if it can be hard, because of OpenGL).
Laurent _______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
participants (3)
-
Julien Jassaud
-
Laurent Sansonetti
-
Michael Johnston