Issue with Day 022 Instantaneous Live Code Editing - FreeLibrary taking too long?

So I'm following along with Casey on Day 022 where we are trying to get our game dll modifications to show up almost instantly after a new build of the project while running the exe. The issue I'm having is it seems that window's "FreeLibrary()" function is taking too long to unload the handmade_temp.dll to open it for writing. The reason I say this is because I would keep getting a failure from window's "CopyFileA()" function with windows error code 32 meaning basically the dll file was being used by another process so it couldn't be written to. After trying a few things I ended up adding a 200ms delay between the "Win32UnloadGameCode()" function and the "Win32LoadGameCode()" function and everything worked. In Casey's stream he does not seem to have this issue and calls "Win32LoadGameCode()" right after the "Win32UnLoadGameCode()" and "FreeLibrary()" seems to be unloading things quickly enough. I will post my relevant code below just to make sure I'm not making a mistake but if not then just wondering if anyone was having this issue and if they were able to come up with a solution.

Win32LoadGameCode:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
local_func Win32_Game_Code
Win32LoadGameCode(const char* GameCodeSourceFileName)
{
	Win32_Game_Code GameCode{};

	GameCode.DLLLastWriteTime = Win32GetFileTime(GameCodeSourceFileName);

	
	const char *GameCodeTempFileName = "handmade_temp.dll";
	if(CopyFileA(GameCodeSourceFileName, GameCodeTempFileName, FALSE) != 0)
	{
		GameCode.DLLHandle = LoadLibraryA(GameCodeTempFileName);
		if (GameCode.DLLHandle)
		{
			GameCode.GameUpdateAndRender = (void (*)(Game_Graphics_Offscreen_Buffer *, Game_Sound_Output_Buffer *, Game_Input *,
													 Game_Memory))SDL_LoadFunction(GameCode.DLLHandle, "GameUpdateAndRender");

			if (!GameCode.GameUpdateAndRender)
			{
				printf("Error: GameUpdateAndRender function not found in dll! SDL error msg: %s\n", SDL_GetError());
			}
		}
		else
		{
			printf("Error: Game code dll file cannont load properly! SDL error msg: %s\n", SDL_GetError());
		}
	}
	else
	{
		printf("Error: Could not copy dll file! Win32 error code: %i", GetLastError());
	}

	return GameCode;
}


Win32UnloadGameCode:

1
2
3
4
5
6
7
local_func void
Win32UnloadGameCode(Win32_Game_Code* GameCode)
{
	FreeLibrary(GameCode->DLLHandle);
	GameCode->DLLHandle = 0;
	GameCode->GameUpdateAndRender = nullptr;
}



Section in main where I call the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
      const char *GameCodeSourceFileName = "handmade.dll";
      Win32_Game_Code GameCode = Win32LoadGameCode(GameCodeSourceFileName);

      while (Running)
      {
           FILETIME NewGameCodeFileWriteTime = Win32GetFileTime(GameCodeSourceFileName);
	   if(CompareFileTime(&NewGameCodeFileWriteTime, &GameCode.DLLLastWriteTime) != 0)
	   {
		Win32FreeGameCode(&GameCode);
		GameCode = Win32LoadGameCode(GameCodeSourceFileName);
	   };
     
        //more code.....



Update:

I also realized that it could be something in my build.bat file as well since its a little different from what Casey is doing due to me trying to use SDL instead of strictly Windows. I have some added include paths and things inside my build.bat file that I'm not sure if that's causing any issues. Still investigating but here is my batch file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@echo off

REM linker debug:fastlink/full options seem to slow the initial runtime of the app when trying to run in the debugger. According to https://developercommunity.visualstudio.com/content/problem/67777/initializing-symbol-search-table-takes-a-long-time.html, this is a microsoft issue that will hopefully be resovled in VS 2017 15.6.

set CommonCompilerFlags= -DHANDMADE_SLOW_BUILD=1 -DHANDMADE_DEVELOPER_BUILD=1 -MT -Gm- -Z7 -nologo -Oi -Od -WX -W3 -GR -EHa-
set CommonLinkerFlags=-subsystem:CONSOLE -machine:x64 -incremental:no -nologo -debug:full -opt:ref

set IncludePaths=-I "w:\handmade\third party\sdl\include"

set LibraryPaths=/LIBPATH:"w:\handmade\third party\sdl\lib\x64"
set Libraries="SDL2.lib" "SDL2main.lib"

IF NOT EXIST build mkdir build
pushd build

REM Build Game Code DLL
del *.pdb > NUL 2> NUL
cl /c w:\handmade\source\handmade.cpp %CommonCompilerFlags% 
link w:\handmade\build\handmade.obj %CommonLinkerFlags% -dll -PDB:handmade_%random%.pdb -export:GameUpdateAndRender 

REM Build Platform exe
cl /c w:\handmade\source\win32_handmade.cpp %CommonCompilerFlags% %IncludePaths%
link  w:\handmade\build\win32_handmade.obj %CommonLinkerFlags% -out:win32_handmade.exe %Libraries% %LibraryPaths%
popd

Edited by Jason on Reason: Added Info:
I believe this issue is fixed in Day 39 - https://hero.handmade.network/episode/code/day039/#3158

Edited by Mārtiņš Možeiko on
Unfortunately that doesn't seem to solve the issue. Now I get the error:


"Fatal error: Cannot open compiler generated file 'W:\handmade\build\win32_handmade.obj" permission denied

Edited by Jason on
So far it seems removing the linker option "debug:full" helps get things to where I only have to delay 5ms to have the code hot load without issues. I guess this was causing the build to take longer and cause the OS to keep locked the dll until finished. However without this option (with visual studio 2017 at least) the debugger can't seem to pickup my breakpoints :-(

Edited by Jason on
What does Visual Studio say when your breakpoints don't work (hovering above a breakpoint in the margin should display a tooltip) ? After the hot-reloading, can you load the symbol file manually (same name as the .dll but with the .pdb extention)?

To load symbols:
- Debug menu > Windows > Modules
- Find the dll in the list, right click > load symbols.

If you did the day 39 fix, could you show us your build.bat file and relevant code ?