"Launch failed" with any application on Linux

I use Nsight Graphics on a Linux distribution with rolling release.

Today I updated the system to kernel 5.14.9 and glibc 2.34, and now the debugger can’t attach to any process. I tried my application, vkcube and several games from Steam whom I debugged earlier.

In each case applications successfully start and work, but Nsight immediately reports

Launch failure: Process creation failure
Launch failed.

and does not attach to it. If I go to Attach tab, it does not show application’s pid. Looks like the application has started without Nsight.

Also the same update for the kernel and glibc broke gpu thread sanboxing on Nvidia gpus in Electron applications. For example, see this thread. Probably this problem and Nsight problem have the same root.

Please let me know if there exists a quick-n-dirty workaround with env vars or something like that.

Hello,
Thank you for using Nsight Graphics and I’m sorry you ran into this issue. I checked in with our engineering team and they suggested the following:

It looks like process injection was broken with the new kernel and glibc.

A quick WAR for the user is trying LD_PRELOAD:

$ LD_PRELOAD=/target/linux-desktop-nomad-x64/libNvda.Graphics.Interception.so NV_TPS_LAUNCH_TOKEN=“Frame Debugger” ENABLE_VK_LAYER_NV_nomad_release_public_2021_4_1=1

Then find the process in attach tab and connect to it. (Note the version needs to match the installed Nsight version in the Vulan layer environment

Thank you for reply!
It works only partially.

I forgot to write that I’m debugging an opengl application. I tried your env vars without the last one, and yes, the process appeared in the attach tab, Nsight connected to it, but the only things I could do are disconnect and terminate.

“Capture for live analysis” button was inactive, and the following was logged:

Note: A frame delimiter has not been seen. If you are using a non-swap/non-present API call to delimit frames, please see the host for an option to change the delimiter that marks a frame.

I use the common way to swap buffers once per frame without any trickery, and earlier it always worked with SwapBuffers frame delimiter.

I also tried to debug my app and vkcube with ENABLE_VK_LAYER_NV_nomad_release_public_2021_4_1=1 and got the same result.

Hello,

Were you using dlsym to get all GL entry points? If this is the case, all GL calls will not be intercepted by Nsight, which leads to the warning.

The solution is to use glXGetProcAddress() instead of dlsym to get GL entry points, so that Nsight can intercept.

Thank you, that works!

Let me write some details of the solution in case anyone else needs it.

I’m using GLEW for entry points and GLFW3 for window management.

GLEW

GLEW uses glXGetProcAddress(), so no problem here.
It loads entry points in glewInit(), which is implemented like this:

GLboolean r = GL_FALSE;

  r = ((glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindFramebuffer")) == NULL) || r;
  r = ((glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbuffer")) == NULL) || r;
  r = ((glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebuffer")) == NULL) || r;
  r = ((glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatus")) == NULL) || r;
.....

where glewGetProcAddress is

#else /* __linux */
#  define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
#endif

where glXGetProcAddressARB is defined as follows:

extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void);

and is taken from libGLX.

GLFW

GLFW3 under all abstraction layers loads glXSwapBuffers with dlsym, which hides it from the debugger. First, let’s expose native intrinsics of GLFW:

#ifdef __linux__
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#include <GLFW/glfw3native.h>
#include <GL/glx.h>
#endif

then replace glfwSwapBuffers(window) with

#ifdef __linux__
		glXSwapBuffers(glfwGetX11Display(), glfwGetGLXWindow(window));
#else
		glfwSwapBuffers(window);
#endif

Launch
When launching OpenGL app it’s important to use libNomad.Injection.so instead of libNvda.Graphics.Interception.so.
Final command line for my app is this:

LD_PRELOAD=/path/to/nvidia/NVIDIA-Nsight-Graphics-2021.4/target/linux-desktop-nomad-x64/libNomad.Injection.so NV_TPS_LAUNCH_TOKEN="Frame Debugger" ./start_demo

Now I’m happy to see my app’s frame from the inside again!