Win64 thread issues


#1

My app has a hidden native win32 window, that listens fro global hotkeys (the way that was shown somewhere here on the forums), it’s a class that’s a Thread class, listens for message events, using a static callback and a pointer to my class it passed events to my MainWindow class. On win32 it workes (i use actionListener/Broadcaster combination to notify my Juce classes), but on WIN64 i get exceptions when i get those events. I was getting them due to MessageManagerLocks (when i tried locking the message manager before touching the GUI part of the main window, i got a application halt so i stopped doing that). So i figured i’ll use AsyncUpdater, but now that causes other errors in _tmain

#ifdef _WINMAIN_


            lpszCommandLine = _twincmdln();
            mainret = _tWinMain( (HINSTANCE)&__ImageBase,
                                 NULL,
                                 lpszCommandLine,
                                 StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                                      ? StartupInfo.wShowWindow
                                      : SW_SHOWDEFAULT
                                ); <- exception
#else  /* _WINMAIN_ */
            _tinitenv = _tenviron;
            mainret = _tmain(__argc, _targv, _tenviron);
#endif  /* _WINMAIN_ */

everthing is fine if i don’t call triggerAsyncUpdate() in my class that gets the info, once i do that, it crashes.

Is there anything specific to WIN64 and different from WIN32 that i should consider ?

the code in the Thread class that i use to create the win32 native window

void Win32NotificationWindow::run()
{
   MSG Msg;
   int rval;

   //
   // register the window class
   //
   WNDCLASSEXA wcex;

   wcex.cbSize				= sizeof(WNDCLASSEX);
   wcex.style				= CS_HREDRAW | CS_VREDRAW;
   wcex.lpfnWndProc			= Win32NotificationWindow::WndProc;
   wcex.cbClsExtra			= 0;
   wcex.cbWndExtra			= 0;
   wcex.hInstance			= GetModuleHandle(NULL);
   wcex.hIcon				= 0;
   wcex.hCursor				= 0;
   wcex.hbrBackground		= (HBRUSH)(COLOR_WINDOW + 1);
   wcex.lpszMenuName		= 0;
   wcex.lpszClassName		= classname;
   wcex.hIconSm				= 0;

   RegisterClassExA(&wcex);

   //
   // make the window
   //
   hWindow = CreateWindowEx (
           0,                   
           (LPCSTR)classname,         
           (LPCSTR)"Winamp Controller Utility",       
           WS_OVERLAPPEDWINDOW, 
           CW_USEDEFAULT,       
           CW_USEDEFAULT,       
           544,                 
           375,                 
           HWND_DESKTOP,        
           NULL,                
           GetModuleHandle(NULL),       
           NULL                 
           );

   if (NULL == hWindow)
   {
	   DWORD e = GetLastError();
	   return;
   }
   else
   {
		const KeyPress kp = KeyPress::createFromDescription (keyCodeDescription);

		if ( RegisterHotKey(hWindow, 0x0aff, kp.getModifiers().getRawFlags(), kp.getKeyCode()) )
		{
			/* */
		}
		else
		{
			DWORD e = GetLastError();
			AlertWindow::showMessageBox (AlertWindow::InfoIcon, T("Global hotkey register error"), T("I was unable to register the global hotkey, maybe try a different combination ") + String ((uint32)e));
		}
   }
   
   //
   // Save the "this" pointer in the window
   //
   if ( (SetWindowLongPtrA(hWindow,(int) GWLP_USERDATA,(__int3264) (LONG_PTR) this) ) == 0)
   {
	   DWORD e = GetLastError();
   }

   //
   // listen to the message loop
   //
   while ( (rval = GetMessage(&Msg, hWindow, 0, 0)) != 0)
   {
      if (-1 == rval)
	  {
		  DWORD e = GetLastError();
		  return;
	  }
	  else
	  {
		  TranslateMessage(&Msg);
		  DispatchMessage(&Msg);
	  }
   }
}

then the WndProc looks like this

LRESULT CALLBACK Win32NotificationWindow::WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   LONG_PTR context;
   Win32NotificationWindow *that;
               
   context = GetWindowLongPtrA (hwnd, GWLP_USERDATA);
   that = (Win32NotificationWindow *) context;

   if (that && uMsg == WM_HOTKEY)
   {
	   that->windowsCallback(lParam);
   }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

and somewhere in windowsCallback i have the triggerAsyncUpdate() called.


#2

I can’t think of any 64-bit specific issues, but you’re not supposed to create windows on background threads - I seem to rememeber that they can only receive messages on the thread that created them. Maybe you just managed to get away with this on win32.

Surely the stack trace of the crash will make it clear what’s going wrong though?


#3

the thing is that it happens only on Release builds, i can’t debug this, the debug build looks fine.


#4

it’s crap i tried pipes but that causes errors too.

would it be possible for JUCE to handle WM_HOTKEY messages and pass them somehow to the app, perhaps all WM_ messages could be passed to the app, and we could deal with them, as long as we get them. im ot of ideas how to do this.


#5

Have you tried creating this window on the normal event thread?


#6

what i did for now (i’m on win32 i can’t test on win64, i’ll go back home and see) i removed the Thread part from the win32window code, since the message comes to me from the callback specified on CreateWindowEx, the Thread is not needed (or at least it looks like it’s not on win32, since it’s working).

but i don’t know how this will act on win64.


#7

well it didn’t work on Win64, the problem was with the win32 class (that holds the win32 native window) it was an ActionBroadcaster, and my MainWindow (DocumentWindow bases class) was the listener, the program failed somewhere after the sendActionMessage and before the message was delivered (some inner workings of JUCE).

Anyway i stored a pointer to MainWindow, and am doing a direct call to the MainWindow method, since it’s the same thread now, MessageManagerLock is not needed, and Win64 does not complain anymore, it works. But i couldn’t use JUCE MessageThread to deliver those messages, event though it’s all the same thread now.

i was going through this article http://www.codeproject.com/KB/vista/vista_x64.aspx#x64_Section and there are a lot of gotchas in the 64bit world. i’m using vista so there is even more.