FAsyncDirectoryReader::ScanDirectory CRASH

Hi There,

I’m getting an occasional crash in the above function.

Suspect it’s related to my use of “FPakPlatformFile::Unmount”. My app involves lots of tiny pak files and I mount / unmount them on the fly.

This is the unmount function (called on the main thread during my game mode Tick function I think).

bool DLCDownloadManager::UnMountPak(const FString &rPakFileName, const DLCMountPointInfo &rMPI)
{
	if (mp_DLCPakFiles)
	{
		if (mp_DLCPakFiles->Unmount(*rPakFileName))
		{
			FPackageName::UnRegisterMountPoint(rMPI.m_MountPoint, rMPI.m_Directory);
			return true;
		}
	}
	return false;
}

-Tom

Hey theonecalledtom,

Can you tell me what crash you are getting? As in, the call stack or error that is generated on crash.

Can you give me more information on how I would recreate this issue? This includes all the steps you go through in order to create the pak files, load the pak files, and then how you are using your UnMountPak function in conjunction with the other steps.

Also, it could help both of us if you follow this:

https://answers.unrealengine.com/questions/12363/how-do-i-report-a-bug.html

Thanks.

It was a terrible bug report :slight_smile:

I pressed close from visual studio right at the moment I decided to report it. There was no crash reporter popup.

This happens every few days at the moment so I’ll be able to grab a call stack etc.

It started with 4.13. My pack file usage has remain constant for a while and though there is plenty of chance that I’m doing something this looks like a bug.

My first guess is that an async process is not notified that the pak file it is scanning is no longer valid.

My pak files are built using unrealpak.exe and a manifest file. They contain images and text files and tend to be small - a few kb to a few mb. They are downloaded via http and saved locally - can also be removed from the app by the user.

My app unmounts pak files all the time. It’s contents are lots of small units and when you switch from one unit to another it unmounts the first, given the frequency of this crash (four times now in a week, hundreds of mount/unmounts in this time) its likely seen much less frequently by other people (or its entirely mine!).

As I say, next time it happens I’ll attach call stack, output, anything else I can divine but t for now I’m sticking with my first guess :wink:

And as for reproing the problem I don’t have an easy solution for you.

I use the engine version (do not build its code from github) but have my own c++ module that is mounting and Unmounting. If you want access to my project (also in git) then that can be provided.

Hey theonecalledtom,

Thanks for the report but with out any reproduction steps or more information on how we can replicate the issue on our end, we cannot move forward. If at any point you have more information on how we can reliably replicate the issue, please post again here and I will continue forward with the investigation. For now, we don’t think this is an actual bug with the Unreal Engine.

Thanks.

Thank you for your response Kyle however my suspicion is that this is a bug with the engine, at the very least if I am mistreating it there should be an assert or error to tell me what the problem is.

It would at least be worth an engineer making sure the async directory scan is appropriately stopped when a pak file is unmounted, or that the unmount function throws an error if called from an unexpected thread or point in the code.

I’ll provide more information when I get it.

Some unmounts are sometimes being triggered in response to http traffic (so come from the http manager update). This might fall outside the expected threading model. I can move them to the main update (for instance during my AGameMode::Tick or something like the code below) but am going to wait for the crash to happen again first.

  FGraphEventRef Task = FFunctionGraphTask::CreateAndDispatchWhenReady([=](){
        onMain();
    }, TStatId(), NULL, ENamedThreads::GameThread);

For the record this bug has disappeared™. Given I didn’t update the engine you can only suspect my code…

It came back :slight_smile:

Callstack of crash:

>	UE4Editor-PakFile.dll!FPakPlatformFile::IterateDirectory(const wchar_t * Directory, IPlatformFile::FDirectoryVisitor & Visitor)  Line 1400 + 0x3 bytes	C++
 	UE4Editor-DirectoryWatcher.dll!DirectoryWatcher::FAsyncDirectoryReader::ScanDirectory(const FString & InDirectory)  Line 360	C++
 	UE4Editor-DirectoryWatcher.dll!DirectoryWatcher::FAsyncDirectoryReader::Tick(const DirectoryWatcher::FTimeLimit & TimeLimit)  Line 277	C++
 	UE4Editor-DirectoryWatcher.dll!DirectoryWatcher::FAsyncTaskThread::Run()  Line 121 + 0x3a bytes	C++
 	UE4Editor-Core.dll!FRunnableThreadWin::Run()  Line 74	C++
 	UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun()  Line 23 + 0x8 bytes	C++

Right at end of IterateDirectory, during the dereference of LowerLevel.

		else
		{
			 // No point in using FPakVisitor as it will only slow things down.
			Result = LowerLevel->IterateDirectory(Directory, Visitor);
		}
	}
	return Result;
}

LowerLevel itself looks valid but its possible that Directory is dodgy.

The Directory parameter is reported 0x1, so an invalid TCHAR pointer, however I think there is a strong chance of my debugger lying due to optimizations.

BUT I’m a little confused by the use of PendingDirectories in FileCache.cpp.

  • Values are passed into ScanDirectory by pointer to memory owned by PendingDirectory.
  • FVisitor in ScanDirectory takes a pointer to this and can call Add on it. Can’t this reallocate the memory that was passed into ScanDirectory in the first place?

At any rate, there are 30 strings in PendingDirectories at the time of the crash, values I’ve checked seem valid. PendingDirectories reallocated at 24 entries when I stepped through so my above suspicion could be misplaced.

I see these notifications in normal flow - at the point where I’m unmounting directories:

[2016.11.11-00.23.19:486][ 78]LogDirectoryWatcher: A directory notification for 'C:/Users/Thomas Shepherd/Documents/Unreal Projects/MM/Content/' was aborted.

Just crashed again, during my app’s user log out process - right after the aborted notification.

Here’s my final output:

[2016.11.29-23.43.12:973][396]LogDirectoryWatcher: A directory notification for 'C:/Users/Thomas Shepherd/Documents/Unreal Projects/MM/Content/' was aborted.
[2016.11.29-23.43.12:987][396]LogDirectoryWatcher: A directory notification for 'C:/Users/Thomas Shepherd/Documents/Unreal Projects/MM/Saved/matchoo/Cache/DesktopEditor/userpublished/818975c30fce' was aborted.
[2016.11.29-23.43.12:988][396]LogTemp:Warning: SaveGase::ResetSave called
[2016.11.29-23.43.12:988][396]LogTemp:Warning: UserData::Reset called
[2016.11.29-23.43.12:988][396]LogTemp:Warning: DLCDownloadManager::Reset called!
Exception thrown at 0x00007ff999511061 (UE4Editor-PakFile.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0xffffffffffffffff.
Unhandled exception at 0x00007ff999511061 (UE4Editor-PakFile.dll) in UE4Editor.exe: 0xC0000005: Access violation reading location 0xffffffffffffffff.

Hey theonecalledtom-

Are you running the project through Visual Studio or directly from the .uproject? If you’re using the .uproject, can you provide the full crash log and callstack? Can you explain exactly what you were working on or doing when it crashed (opened a blueprint, editing a material, playing in editor, etc)? If you’re able to provide a sample project that reproduces the crash, please let me know along with any steps to cause the crash so I can investigate the issue directly.

Hi Doug - running through Visual Studio - my C++ code is mounting and unmounting pak files.

Just after the unmount I sometimes get this crash - twice in the last couple of days but for a couple of weeks prior had no crashes. Note that I mount and unmount DLC packages all the time (multiple times per hour, 10 hours per day) so this is a fairly low frequency bug and most games I’ve worked on would rarely see it as normally you mount and unmount packages on a far lower frequency.

I’m not likely to have time to make a test project this year.

The following are extracted from my DLC package code.

Mounting:

mp_DLCPakFiles->Mount(*rPakFileName, 0, *StandardFilename);
FPackageName::RegisterMountPoint(rMPI.m_MountPoint, StandardFilename);

Unmounting:

mp_DLCPakFiles->Unmount(*rPakFileName);
FPackageName::UnRegisterMountPoint(rMPI.m_MountPoint, rMPI.m_Directory);

Oh - and I’m playing in the editor.

Not seen since updating to 4.14

Hi Tom,

I am glad to hear that the issue appears to have been resolved for you. If you see it appear again, please let us know.

Tim

Well. After not seeing this in a while it’s back (though I sometimes get crashes when not attached to a debugger - perhaps this is one…).

Looks like a partial destruction of the directory scanning task data while it’s still running.

If I can ask for this task to stop in my code that might help me.

Repro steps would be the same, unmount a pak file while the directory scanner is running. Perhaps do it 1000 times. Your engineers should have some stability tests that they can apply to this. Show them the info I’m attaching

Note that Pending files array is garbage data. as is TaskArrayMutex. PendingDirectories contains valid data.

See comment below with attached crash info.

It’s back!

It might happen faster by forcing the Unmount soon after the Mount. Not sure.