kmonsoor / pyglet

Automatically exported from code.google.com/p/pyglet
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Multiple run()/exit() calls on OSX leads to error (and likely later segfault) #728

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Using latest Pyglet "tip.zip" on OSX 10.9.2 (MacBook Air w/NVIDIA). Running the 
following code:

import pyglet
class Tester(pyglet.window.Window):
    def on_draw(self):
        pyglet.app.exit()
Tester()
pyglet.app.run()
Tester()
pyglet.app.run()

Causes this output on OSX:

2014-04-04 14:39:40.718 Python[21164:d0f] ApplePersistenceIgnoreState: Existing 
state will not be touched. New state will be written to 
/var/folders/tq/wjh49th52_5bc8w5fm7sz4600000gn/T/org.python.python.savedState
2014-04-04 14:39:40.966 Python[21164:d0f] _createMenuRef called with existing 
principal MenuRef already associated with menu
2014-04-04 14:39:40.968 Python[21164:d0f] (
    0   CoreFoundation                      0x00007fff8c51925c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff8f1d8e75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8c51910c +[NSException raise:format:] + 204
    3   AppKit                              0x00007fff8f6d3e84 -[NSCarbonMenuImpl _createMenuRef] + 62
    4   AppKit                              0x00007fff8f6d385a -[NSCarbonMenuImpl _instantiateCarbonMenu] + 143
    5   AppKit                              0x00007fff8f6d2022 -[NSApplication finishLaunching] + 876
    6   _ctypes.so                          0x00000001005c0534 ffi_call_unix64 + 76
    7   ???                                 0x00007fff5fbfa860 0x0 + 140734799784032
)

The first line about "savedState" seems to be benign enough, since it always 
happens (although it would be nice to suppress somehow):

>>> import pyglet
>>> pyglet.window.Window()
2014-04-04 14:57:57.522 Python[21320:d0f] ApplePersistenceIgnoreState: Existing 
state will not be touched. New state will be written to 
/var/folders/tq/wjh49th52_5bc8w5fm7sz4600000gn/T/org.python.python.savedState
CocoaWindow(width=640, height=480)
>>> exit()

However, the subsequent "_createMenuRef" error seems specific to calling 
`run()`/`exit()` more than once. When used in a larger codebase in a more 
complex example, I end up eventually getting a segfault, which I suspect is 
caused by this -- when I remove the extra calls to `run()`/`exit()` in that 
example, the segfault goes away. No such error happens on Ubuntu Linux, which I 
also use for testing.

If you have any ideas of how to debug this further, let me know. I'll try to do 
some digging on my own in the meantime.

Output of `python -m pyglet.info`:

Python
------------------------------------------------------------------------------
sys.version: 2.7.3 | 64-bit | (default, Aug  8 2013, 05:37:06) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
sys.platform: darwin
sys.maxint: 9223372036854775807
PyObjC not available
os.getcwd(): /Users/larsoner/custombuilds/vispy

pyglet
------------------------------------------------------------------------------
pyglet.version: 1.2alpha1
pyglet.__file__: 
/Users/larsoner/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/
pyglet/__init__.pyc
pyglet.options['search_local_libs'] = True
pyglet.options['debug_win32'] = False
pyglet.options['xlib_fullscreen_override_redirect'] = False
pyglet.options['debug_trace_args'] = False
pyglet.options['font'] = ('gdiplus', 'win32')
pyglet.options['debug_gl_trace_args'] = False
pyglet.options['debug_trace'] = False
pyglet.options['debug_gl_trace'] = False
pyglet.options['debug_x11'] = False
pyglet.options['debug_media'] = False
pyglet.options['debug_trace_depth'] = 1
pyglet.options['vsync'] = None
pyglet.options['debug_gl'] = True
pyglet.options['darwin_cocoa'] = True
pyglet.options['debug_trace_flush'] = True
pyglet.options['shadow_window'] = True
pyglet.options['xsync'] = True
pyglet.options['debug_font'] = False
pyglet.options['graphics_vbo'] = True
pyglet.options['debug_lib'] = False
pyglet.options['debug_graphics_batch'] = False
pyglet.options['audio'] = ('directsound', 'pulse', 'openal', 'silent')
pyglet.options['debug_texture'] = False

pyglet.window
------------------------------------------------------------------------------
2014-04-04 14:41:44.830 Python[21183:d0f] ApplePersistenceIgnoreState: Existing 
state will not be touched. New state will be written to 
/var/folders/tq/wjh49th52_5bc8w5fm7sz4600000gn/T/org.python.python.savedState
platform: <pyglet.window.Platform object at 0x10069bb10>
display: <pyglet.canvas.cocoa.CocoaDisplay object at 0x1023f0810>
screens[0]: CocoaScreen(x=0, y=0, width=1440, height=900)
config['double_buffer'] = 1
config['stereo'] = 0
config['buffer_size'] = 32
config['aux_buffers'] = 0
config['sample_buffers'] = 0
config['samples'] = 0
config['red_size'] = 0
config['green_size'] = 0
config['blue_size'] = 0
config['alpha_size'] = 8
config['depth_size'] = 24
config['stencil_size'] = 0
config['accum_red_size'] = 0
config['accum_green_size'] = 0
config['accum_blue_size'] = 0
config['accum_alpha_size'] = 0
config['major_version'] = None
config['minor_version'] = None
config['forward_compatible'] = None
config['debug'] = None
context: CocoaContext()

window.context._info
------------------------------------------------------------------------------
gl_info.get_version(): 2.1 NVIDIA-8.24.11 310.90.9b01
gl_info.get_vendor(): NVIDIA Corporation
gl_info.get_renderer(): NVIDIA GeForce 320M OpenGL Engine
gl_info.get_extensions():
   GL_APPLE_aux_depth_stencil
   GL_APPLE_client_storage
   GL_APPLE_element_array
   GL_APPLE_fence
   GL_APPLE_float_pixels
   GL_APPLE_flush_buffer_range
   GL_APPLE_flush_render
   GL_APPLE_object_purgeable
   GL_APPLE_packed_pixels
   GL_APPLE_pixel_buffer
   GL_APPLE_rgb_422
   GL_APPLE_row_bytes
   GL_APPLE_specular_vector
   GL_APPLE_texture_range
   GL_APPLE_transform_hint
   GL_APPLE_vertex_array_object
   GL_APPLE_vertex_array_range
   GL_APPLE_vertex_point_size
   GL_APPLE_vertex_program_evaluators
   GL_APPLE_ycbcr_422
   GL_ARB_color_buffer_float
   GL_ARB_depth_buffer_float
   GL_ARB_depth_clamp
   GL_ARB_depth_texture
   GL_ARB_draw_buffers
   GL_ARB_draw_elements_base_vertex
   GL_ARB_draw_instanced
   GL_ARB_fragment_program
   GL_ARB_fragment_program_shadow
   GL_ARB_fragment_shader
   GL_ARB_framebuffer_object
   GL_ARB_framebuffer_sRGB
   GL_ARB_half_float_pixel
   GL_ARB_half_float_vertex
   GL_ARB_imaging
   GL_ARB_instanced_arrays
   GL_ARB_multisample
   GL_ARB_multitexture
   GL_ARB_occlusion_query
   GL_ARB_pixel_buffer_object
   GL_ARB_point_parameters
   GL_ARB_point_sprite
   GL_ARB_provoking_vertex
   GL_ARB_seamless_cube_map
   GL_ARB_shader_objects
   GL_ARB_shader_texture_lod
   GL_ARB_shading_language_100
   GL_ARB_shadow
   GL_ARB_sync
   GL_ARB_texture_border_clamp
   GL_ARB_texture_compression
   GL_ARB_texture_compression_rgtc
   GL_ARB_texture_cube_map
   GL_ARB_texture_env_add
   GL_ARB_texture_env_combine
   GL_ARB_texture_env_crossbar
   GL_ARB_texture_env_dot3
   GL_ARB_texture_float
   GL_ARB_texture_mirrored_repeat
   GL_ARB_texture_non_power_of_two
   GL_ARB_texture_rectangle
   GL_ARB_texture_rg
   GL_ARB_transpose_matrix
   GL_ARB_vertex_array_bgra
   GL_ARB_vertex_blend
   GL_ARB_vertex_buffer_object
   GL_ARB_vertex_program
   GL_ARB_vertex_shader
   GL_ARB_window_pos
   GL_ATI_separate_stencil
   GL_ATI_texture_env_combine3
   GL_ATI_texture_float
   GL_ATI_texture_mirror_once
   GL_EXT_abgr
   GL_EXT_bgra
   GL_EXT_bindable_uniform
   GL_EXT_blend_color
   GL_EXT_blend_equation_separate
   GL_EXT_blend_func_separate
   GL_EXT_blend_minmax
   GL_EXT_blend_subtract
   GL_EXT_clip_volume_hint
   GL_EXT_compiled_vertex_array
   GL_EXT_debug_label
   GL_EXT_debug_marker
   GL_EXT_depth_bounds_test
   GL_EXT_draw_buffers2
   GL_EXT_draw_range_elements
   GL_EXT_fog_coord
   GL_EXT_framebuffer_blit
   GL_EXT_framebuffer_multisample
   GL_EXT_framebuffer_multisample_blit_scaled
   GL_EXT_framebuffer_object
   GL_EXT_framebuffer_sRGB
   GL_EXT_geometry_shader4
   GL_EXT_gpu_program_parameters
   GL_EXT_gpu_shader4
   GL_EXT_multi_draw_arrays
   GL_EXT_packed_depth_stencil
   GL_EXT_packed_float
   GL_EXT_provoking_vertex
   GL_EXT_rescale_normal
   GL_EXT_secondary_color
   GL_EXT_separate_specular_color
   GL_EXT_shadow_funcs
   GL_EXT_stencil_two_side
   GL_EXT_stencil_wrap
   GL_EXT_texture_array
   GL_EXT_texture_compression_dxt1
   GL_EXT_texture_compression_s3tc
   GL_EXT_texture_env_add
   GL_EXT_texture_filter_anisotropic
   GL_EXT_texture_integer
   GL_EXT_texture_lod_bias
   GL_EXT_texture_mirror_clamp
   GL_EXT_texture_rectangle
   GL_EXT_texture_sRGB
   GL_EXT_texture_sRGB_decode
   GL_EXT_texture_shared_exponent
   GL_EXT_timer_query
   GL_EXT_transform_feedback
   GL_EXT_vertex_array_bgra
   GL_IBM_rasterpos_clip
   GL_NV_blend_square
   GL_NV_conditional_render
   GL_NV_depth_clamp
   GL_NV_fog_distance
   GL_NV_fragment_program2
   GL_NV_fragment_program_option
   GL_NV_light_max_exponent
   GL_NV_multisample_filter_hint
   GL_NV_point_sprite
   GL_NV_texgen_reflection
   GL_NV_texture_barrier
   GL_NV_vertex_program2_option
   GL_NV_vertex_program3
   GL_SGIS_generate_mipmap
   GL_SGIS_texture_edge_clamp
   GL_SGIS_texture_lod

pyglet.gl.glu_info
------------------------------------------------------------------------------
glu_info.get_version(): 1.3 MacOSX
glu_info.get_extensions():

pyglet.gl.glx_info
------------------------------------------------------------------------------
GLX not available.

pyglet.media
------------------------------------------------------------------------------
audio driver: <pyglet.media.drivers.openal.OpenALDriver object at 0x104414f90>

pyglet.media.avbin
------------------------------------------------------------------------------
AVbin not available.

pyglet.media.drivers.openal
------------------------------------------------------------------------------
Library: <CDLL '/System/Library/Frameworks/OpenAL.framework/OpenAL', handle 
1022460f0 at 104437cd0>
Version: (1, 1)
Extensions:
   ALC_EXT_CAPTURE
   ALC_ENUMERATION_EXT
   ALC_EXT_MAC_OSX
   ALC_EXT_ASA
   ALC_EXT_ASA_DISTORTION
   ALC_EXT_ASA_ROGER_BEEP

pyglet.input.wintab
------------------------------------------------------------------------------
WinTab not available.

Original issue reported on code.google.com by larson.e...@gmail.com on 4 Apr 2014 at 10:00

GoogleCodeExporter commented 9 years ago
I think I figured out what was causing the segfault.

In the cocoa `run` code, a `self.pool` is created and drained. However, the 
last pool created never gets drained, even after `self.stop` is called. This is 
dangerous -- I was running Pyglet code alongside some GLFW code, and GLFW must 
also go through Cocoa -- at one point GLFW polled for events, and this caused a 
segfault presumably because Cocoa tried to access the old pool, which had been 
garbage collected by Python.

This fixes the segfault:

https://code.google.com/r/larsonericd-clone/source/detail?r=c84337d5292a469571bd
50e33302c7a231a9fb91

I'm not 100% sure this is the right fix. For example, if one calls `start()` 
followed by `stop()` and then `start()` again, `start()` will not create a 
pool. This makes me wonder if `self.pool` should be initialized in `start()` 
instead of `__init__`. In any case, I'm pretty sure `stop` needs to clear 
`self.pool` to avoid leaving it open.

The other change that's in there is that I commented out the `finishLaunching` 
call. It seems like this can cause problems, e.g.:

http://stackoverflow.com/questions/7381345/cocoa-exception-createmenuref-called-
with-existing-principal-menuref-already-a

Again, not sure if this is the correct solution, but it seems to work on my 
system with my examples, and gets rid of the ugly `_createMenuRef` warning. 
Note that other packages that use Pyglet (e.g., PsychoPy) have noted this issue 
if you google it.

So, I've made some progress, but it's important that someone (preferably much) 
more familiar with Cocoa than me takes a look, and sees if this is a proper 
fix. Cheers!

----------------
FYI the first silly line about `ApplePersistenceIgnoreState` can be dealt with 
by doing:

defaults write org.python.python ApplePersistenceIgnoreState NO

This has something to do with Mavericks and its app restoring, and probably 
isn't specific to Pyglet necessarily (although it looked like there was some 
code in `cocoa.py` that was meant to deal with it already).

Original comment by larson.e...@gmail.com on 20 Apr 2014 at 12:23

GoogleCodeExporter commented 9 years ago

Original comment by useboxnet on 20 Apr 2014 at 8:57