Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Humblest

Member Since 08 Jan 2013
Offline Last Active Jan 09 2013 01:09 AM

Topics I've Started

Does wglMakeCurrent() leak memory in a worker thread?

08 January 2013 - 03:04 AM

Hi, all:

I've been programming server-side offscreen rendering with OpenGL under MS Windows. The workflow consists of the following steps:
1. A client sends a request for volume rendering.
2. Server receives the request, forks a worker thread to do some ray-casting with parameters contained in the request.
3. Server retrieves the rendered image, sends it to the client and terminates the worker thread.

It works fine at first. However, after 10,000 requests, wglMakeCurrent() will fail and significant memory leak can be detected. So I make a simplified test program which contains only OpenGL context creation and deletion. It's shown below. wglMakeCurrent() always fails after about 10,000 loops. Can somebody tell me if there's anything wrong with the code? I'm using Nvidia Quadro GPU, the driver version is 307.45, OS is Windows 7 64-bit.

 

 

#include <cstdio>
#include <windows.h>
#include <tchar.h>
#include <process.h>

LRESULT CALLBACK WndProc_GL(HWND handle, UINT message, WPARAM w_param, LPARAM l_param)
{
  return DefWindowProc(handle, message, w_param, l_param);
}//-------------------------------------------------------

unsigned int __stdcall OpenglThreadProc(void *ptr_input)
{
  HINSTANCE inst_handle = GetModuleHandle(NULL);
  WNDCLASS wnd_class = {CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
    (WNDPROC)WndProc_GL,
    0, 0, inst_handle, NULL, NULL, NULL, NULL,
    _T("OpenGL Hidden Window Class")
  };
  if (!RegisterClass(&wnd_class)) return 0;
  HWND window_handle = CreateWindow(_T("OpenGL Hidden Window Class"),
    _T("Window For OpenGL"),
    WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDRE N, 0, 0, 256, 256,
    NULL, NULL, inst_handle, NULL);
  if (!window_handle) return 0;
  HDC dc_handle = GetDC(window_handle);
  PIXELFORMATDESCRIPTOR ogl_pfd = {sizeof(PIXELFORMATDESCRIPTOR), 1,
    PFD_SUPPORT_OPENGL,
    PFD_TYPE_RGBA, 32,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    24, 8, 0,
    PFD_MAIN_PLANE,
    0, 0, 0, 0
  };
  int pixel_format = ChoosePixelFormat(dc_handle, &ogl_pfd);
  if (!SetPixelFormat(dc_handle, pixel_format, &ogl_pfd)) return 0;
    HGLRC rc_handle = wglCreateContext(dc_handle);
  if (!rc_handle || !wglMakeCurrent(dc_handle, rc_handle)) return 0;

  _tprintf_s(_T("Executing Thread %d.\n"), *(reinterpret_cast<int*>(ptr_input)) + 1);

  // Deletes OpenGL context and destroys window.
  wglMakeCurrent(NULL, NULL);
  wglDeleteContext(rc_handle);
  ReleaseDC(window_handle, dc_handle);
  DestroyWindow(window_handle);
  UnregisterClass(_T("OpenGL Hidden Window Class"), GetModuleHandle(NULL));
  return 1;
}//--------

int main (const int argc, TCHAR *argv[])
{
  int i = 0;
  for (; i < 20000; i++) {
    HANDLE running_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
      OpenglThreadProc, &i, 0, NULL));
    WaitForSingleObject(running_thread, INFINITE);
    CloseHandle(running_thread);
  }
  return 1;
}//---------

 

 

I found something confusing with this test program. wglMakeCurrent() creates a Windows user object every time it's called, but this object is not released in wglDeleteContext(). It still exists even after the worker is terminated, causing a memory leak. There is a per-process limit of user objects under Windows, so the program will eventually fail.

When the code of context creation/deletion is moved to the main thread, wglMakeCurrent() doesn't create new user object after the first invocation. So it seems that wglMakeCurrent() only create new user object in new threads. But since the OpenGL context is explicitly deleted and the thread is terminated, resources associated with that context should be released as well. I'm not sure it's the fault with my code or the driver. Can somebody help me with this?


PARTNERS