www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Win32 Application Error

reply Loopback <elliott.darfink gmail.com> writes:
Hi!

I've recently been using D to program win32 executables. On the official
D site (d-programming-language.org) there is a template of how a basic
win32 executable is supposed to be. In this template you are supposed to
initialize and terminate the D runtime. If I understand correctly this
runtime is related to garbage collection and static con- and
destructors.

This snippet below from my own code works perfectly fine at my
other computer (though both of my computers uses the exact same OS;
win7 x64 Ultimate).

My problem occurs when I terminate the runtime. With one of my computers
it works flawlessly, while on this computer the application hangs up on
exit. I've debugged the code located it to where I terminate the
runtime. The application stops responding completely. Now the
interesting part is that the application do close, but the process still
runs. So you do not notice it at all practically, until you check in the
task manager. The process ends after a while, varying from 5 seconds to
50 seconds.

This is what happens if I press the close button (in the corner). If I
close the program with PostQuitMessage(0) instead, the application is
still visible but a "Program is not resonding" appears. This also
happens at "runtime terminate".

So my question is; how should I avoid these "process still running" and
program not responding errors?

(if worth mentioning, the program itself works perfectly fine, it is
just at exit the program 'bugs').

The code below is my main.d file.

// Win32 Imports
import win32.windef;
import win32.winuser;

// STD&Core Includes
import core.runtime;
import std.utf;

// Custom Includes
import cwindow;
import global;

// Application Entry Point
extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE 
hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	int result;
	
	void exceptionHandler(Throwable e) { throw e; }
	
	try
	{
		// Start Runtime
		Runtime.initialize(&exceptionHandler);
		
		// Create Application
		CWindow wndw = new CWindow(hInstance);
		
		// Control Object
		if(wndw !is null)
			result = 1;
			
		// Terminate Runtime
		Runtime.terminate(&exceptionHandler); // It always crashes here
	}
	
	catch(Throwable o)
	{
		MessageBoxW(null, o.toString().toUTF16z, "Error", MB_OK | 
MB_ICONEXCLAMATION);
		result = 0;
	}
	
	return result;
}
Jun 28 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
It's hard to tell what's going on when we can't see the code for
CWindow. Otherwise your code seems to be the same as the template so
that part should be fine.

Otherwise if you're using multithreading it might be a good idea to
call ExitProcess(result) after PostQuitMessage(), as calling
PostQuitMessage() alone will not terminate any background threads that
you've spawned from D which are looping infinetly.
Jun 28 2011
prev sibling next sibling parent Loopback <elliott.darfink gmail.com> writes:
Thank you for your reply!

I do not use multi-threading so it is not related to that. Though I do
have located the error. It seems as if the application only hangs/delays
application exit, when I load a texture file with DirectX. To be
specific, the function in this case is D3DXCreateTextureFromFileExW.

I still do not see though why the terminate function call fails. Since
the same code works on my other computer. I've also used DirectX debug,
and checking all HRESULTs (success or failure basically). The DirectX
debug output does not display any errors nor warnings and all HRESULTs
returns successfully. The texture loaded with the function does also
work flawlessly, likewise the free memory functions for the textures.

Below is the code that I use for loading and releasing textures:

class (...)

IDirect3DTexture9 LoadTexture(IDirect3DDevice9 device, string fileName, 
D3DXIMAGE_INFO * info = NULL)
{
	// Check if the texture has already been allocated
	IDirect3DTexture9 * pTexture = (fileName in m_textures);
		
	// Return it then
	if(pTexture !is null)
		return *pTexture;
		
	// If not, create a new one
	IDirect3DTexture9 texture;
		
	// Allocate It
	if(FAILED(D3DXCreateTextureFromFileExW(device, fileName.toUTF16z, 
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, 
D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 0, info, NULL, &texture)))
		return null;
		
	// Return it
	return m_textures[fileName] = texture;
}

void Destroy()
{
	foreach(string key; m_textures.keys)
		m_textures[key].Release();
}

// The associative array
IDirect3DTexture9[string] m_textures;
Jun 28 2011
prev sibling parent reply Loopback <elliott.darfink gmail.com> writes:
One more thing, would it perhaps help if I supplied a delegate to
the terminate function, since that may output debug messages?

I would gladly try it but I am not sure how this supplied delegate is
supposed to be.

Also want to mention that the initialize functions returns successfully.
Jun 28 2011
parent Loopback <elliott.darfink gmail.com> writes:
Please ignore. Sadly I hadn't learned the D reference just enough and I
did not realize that the base destructor of a class is still called.
Jun 29 2011