Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault with glGenBuffers/glDeleteBuffers on Nvidia when the thread/program exits #1027

Open
micheal65536 opened this issue Dec 2, 2024 · 1 comment

Comments

@micheal65536
Copy link

Version

3.3.4

Platform

Linux x64

JDK

OpenJDK 8

Module

EGL, GLES

Bug description

On Nvidia GTX 1070 I am experiencing the following segfaults:

  • if glGenBuffers is called at any point with an array size that is not an exact multiple of 128, the program later segfaults when the relevant thread exits
  • if glDeleteBuffers is called at any point, the program segfaults when the relevant thread exits (not immediately after the call to glDeleteBuffers)

No issue on integrated Intel HD graphics.

public static void crash(int count, boolean delete)
{
	long offscreenDisplay = EGL15.eglGetDisplay(EGL15.EGL_DEFAULT_DISPLAY);
	EGL15.eglInitialize(offscreenDisplay, new int[]{0}, new int[]{0});

	PointerBuffer config = PointerBuffer.allocateDirect(1);
	EGL15.eglChooseConfig(offscreenDisplay, new int[]{
			EGL15.EGL_RENDERABLE_TYPE, EGL15.EGL_OPENGL_ES3_BIT,
			EGL15.EGL_SURFACE_TYPE, EGL15.EGL_PBUFFER_BIT,
			EGL15.EGL_RED_SIZE, 8,
			EGL15.EGL_GREEN_SIZE, 8,
			EGL15.EGL_BLUE_SIZE, 8,
			EGL15.EGL_ALPHA_SIZE, 8,
			EGL15.EGL_DEPTH_SIZE, 0,
			EGL15.EGL_STENCIL_SIZE, 0,
			EGL15.EGL_NONE
	}, config, new int[]{0});

	long offscreenSurface = EGL15.eglCreatePbufferSurface(offscreenDisplay, config.get(0), new int[]{
			EGL15.EGL_WIDTH, 8, EGL15.EGL_HEIGHT, 8,
			EGL15.EGL_NONE
	});

	long offscreenContext = EGL15.eglCreateContext(offscreenDisplay, config.get(0), EGL15.EGL_NO_CONTEXT, new int[]{
			EGL15.EGL_CONTEXT_CLIENT_VERSION, 3,
			EGL15.EGL_NONE
	});

	EGL15.eglMakeCurrent(offscreenDisplay, offscreenSurface, offscreenSurface, offscreenContext);
	GLES.createCapabilities();

	int[] ids = new int[count];
	GLES30.glGenBuffers(ids);

	if (delete)
	{
		GLES30.glDeleteBuffers(ids);
	}

	EGL15.eglMakeCurrent(offscreenDisplay, EGL15.EGL_NO_SURFACE, EGL15.EGL_NO_SURFACE, EGL15.EGL_NO_CONTEXT);
	EGL15.eglDestroyContext(offscreenDisplay, offscreenContext);
	EGL15.eglDestroySurface(offscreenDisplay, offscreenSurface);
	EGL15.eglTerminate(offscreenDisplay);
}

The following will trigger the segfault after ~5 seconds, after the "exiting thread" message is displayed:

new Thread(() ->
{
	crash(3, false);

	System.out.println("still alive");
	try
	{
		Thread.sleep(5000);
	}
	catch (InterruptedException exception)
	{
		//
	}
	System.out.println("exiting thread");
}).start();

Examples of parameters which crash:

crash(3, false);
crash(129, false);
crash(128, true);
crash(256, true);

Does not crash:

crash(128, false);
crash(256, false);

I suspect use after free in the Nvidia library implementation but I can't construct a native example with the same/similar behavior. The 128 "alignment" aspect may be specific to my particular system/JVM version and it's possible that other alignments may behave differently on different systems.

Stacktrace or crash log output

No response

@Spasi
Copy link
Member

Spasi commented Dec 7, 2024

Hey @micheal65536,

I cannot reproduce this (on Windows with NV GPU). Gen/DeleteBuffers have no such alignment/size requirements and it sounds very odd that they'd behave like that.

One thing you could try is replacing the int array with an IntBuffer:

try (MemoryStack stack = stackPush())
{
    IntBuffer ids = stack.mallocInt(count);
    GLES20.glGenBuffers(ids);

    if (delete)
    {
        GLES20.glDeleteBuffers(ids);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants