Bug 105090

Summary: shader compilation leaks glsl_type instances
Product: Mesa Reporter: Simon Hausmann <simon.hausmann>
Component: glsl-compilerAssignee: mesa-dev
Status: RESOLVED NOTABUG QA Contact: Intel 3D Bugs Mailing List <intel-3d-bugs>
Severity: normal    
Priority: medium    
Version: git   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments: Simple EGL/GLES test-case that demonstrates the leak

Description Simon Hausmann 2018-02-14 11:47:16 UTC
Created attachment 137352 [details]
Simple EGL/GLES test-case that demonstrates the leak

Compiling a trivial shader will leak glsl_type instances. The following minimal test-case demonstrates the issue when run with valgrind. The output of the incremental leak check should be empty, but it isn't. Alternatively, if you remove the valgrind bits and call the createAndDeleteShader() function in an endless loop, you can observe the memory usage going up slowly. Below is just an excerpt -- I have attached the complete test case separately.

static const char *shaderSource = "void main(){}";

static void createAndDeleteShader()
{
    GLuint shader = glCreateShader(GL_VERTEX_SHADER);
    if (!shader) {
        fprintf(stderr, "Error creating shader\n");
    }
    glShaderSource(shader, 1, &shaderSource, 0);
    glCompileShader(shader);
    glDeleteShader(shader);
}

int main()
{
    ...
    createAndDeleteShader();

    VALGRIND_DO_LEAK_CHECK;

    createAndDeleteShader();

    fprintf(stderr, "---- Memory leaks:\n");
    VALGRIND_DO_CHANGED_LEAK_CHECK;
    fprintf(stderr, "----\n");
    ...
}

The valgrind trace shows that the glsl_type instances used as key in the various type hashes (array_types, record_types, etc.) in glsl_types.cpp are leaked:

==30791== 61 (+61) bytes in 1 (+1) blocks are possibly lost in loss record 882 of 23,604
==30791==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30791==    by 0x8813BAC: ralloc_size (ralloc.c:121)
==30791==    by 0x8813FF4: ralloc_array_size (ralloc.c:208)
==30791==    by 0x8813FF4: ralloc_strdup (ralloc.c:353)
==30791==    by 0x87F63C1: glsl_type::glsl_type(glsl_struct_field const*, unsigned int, glsl_interface_packing, bool, char const*) (glsl_types.cpp:147)
==30791==    by 0x87F82E4: glsl_type::get_interface_instance(glsl_struct_field const*, unsigned int, glsl_interface_packing, bool, char const*) (glsl_types.cpp:1145)
==30791==    by 0x87B9AED: construct_interface_instance (builtin_variables.cpp:352)
==30791==    by 0x87B9AED: generate_varyings (builtin_variables.cpp:1406)
==30791==    by 0x87B9AED: _mesa_glsl_initialize_variables(exec_list*, _mesa_glsl_parse_state*) (builtin_variables.cpp:1436)
==30791==    by 0x8782BEB: _mesa_ast_to_hir(exec_list*, _mesa_glsl_parse_state*) (ast_to_hir.cpp:127)
==30791==    by 0x87E8C46: _mesa_glsl_compile_shader (glsl_parser_extras.cpp:2103)
==30791==    by 0x865728F: _mesa_compile_shader (shaderapi.c:1128)
==30791==    by 0x108D8B: createAndDeleteShader (in /home/simon/gltest/gltest)
==30791==    by 0x108FA5: main (in /home/simon/gltest/gltest)
==30791== 
==30791== 408 (+408) bytes in 1 (+1) blocks are possibly lost in loss record 23,047 of 23,604
==30791==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30791==    by 0x8813BAC: ralloc_size (ralloc.c:121)
==30791==    by 0x8813C88: rzalloc_size (ralloc.c:153)
==30791==    by 0x87F63D9: glsl_type::glsl_type(glsl_struct_field const*, unsigned int, glsl_interface_packing, bool, char const*) (glsl_types.cpp:148)
==30791==    by 0x87F82E4: glsl_type::get_interface_instance(glsl_struct_field const*, unsigned int, glsl_interface_packing, bool, char const*) (glsl_types.cpp:1145)
==30791==    by 0x87B9AED: construct_interface_instance (builtin_variables.cpp:352)
==30791==    by 0x87B9AED: generate_varyings (builtin_variables.cpp:1406)
==30791==    by 0x87B9AED: _mesa_glsl_initialize_variables(exec_list*, _mesa_glsl_parse_state*) (builtin_variables.cpp:1436)
==30791==    by 0x8782BEB: _mesa_ast_to_hir(exec_list*, _mesa_glsl_parse_state*) (ast_to_hir.cpp:127)
==30791==    by 0x87E8C46: _mesa_glsl_compile_shader (glsl_parser_extras.cpp:2103)
==30791==    by 0x865728F: _mesa_compile_shader (shaderapi.c:1128)
==30791==    by 0x108D8B: createAndDeleteShader (in /home/simon/gltest/gltest)
==30791==    by 0x108FA5: main (in /home/simon/gltest/gltest)
==30791== 
==30791== 571 (+571) bytes in 9 (+9) blocks are possibly lost in loss record 23,191 of 23,604
==30791==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30791==    by 0x8813BAC: ralloc_size (ralloc.c:121)
==30791==    by 0x8813FF4: ralloc_array_size (ralloc.c:208)
==30791==    by 0x8813FF4: ralloc_strdup (ralloc.c:353)
==30791==    by 0x87F6428: glsl_type::glsl_type(glsl_struct_field const*, unsigned int, glsl_interface_packing, bool, char const*) (glsl_types.cpp:152)
==30791==    by 0x87F82E4: glsl_type::get_interface_instance(glsl_struct_field const*, unsigned int, glsl_interface_packing, bool, char const*) (glsl_types.cpp:1145)
==30791==    by 0x87B9AED: construct_interface_instance (builtin_variables.cpp:352)
==30791==    by 0x87B9AED: generate_varyings (builtin_variables.cpp:1406)
==30791==    by 0x87B9AED: _mesa_glsl_initialize_variables(exec_list*, _mesa_glsl_parse_state*) (builtin_variables.cpp:1436)
==30791==    by 0x8782BEB: _mesa_ast_to_hir(exec_list*, _mesa_glsl_parse_state*) (ast_to_hir.cpp:127)
==30791==    by 0x87E8C46: _mesa_glsl_compile_shader (glsl_parser_extras.cpp:2103)
==30791==    by 0x865728F: _mesa_compile_shader (shaderapi.c:1128)
==30791==    by 0x108D8B: createAndDeleteShader (in /home/simon/gltest/gltest)
==30791==    by 0x108FA5: main (in /home/simon/gltest/gltest)

Those instances are allocated on the global mem_ctx ralloc context and are therefore "leaking".
Comment 1 Tapani Pälli 2018-02-14 11:55:29 UTC
Since this is EGL your program should call following at the very end:

eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(egl_dpy);

This will cleanup all the resources properly, as per spec glDeleteShader, glDeleteProgram only marks shader for deletion but does not actually delete it right away.

However for a server application, there actually exists bug #104884 which is related to these very same resources as well.
Comment 2 Simon Hausmann 2018-02-14 11:56:54 UTC
Ah yes, bug #104884 is exactly what I'm looking for - I came to the same conclusion.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.