Microsoft Edge not responding after start-up
Introduction
After upgrading Microsoft Edge, some users in a Citrix Server 2016 environment had the problem that Microsoft Edge hangs after starting.
The behavior can vary (sometimes the whole page is blank). However, because the problem has affected some users, it is worth taking a closer look.
First troubleshooting
It was found relatively quickly that a new Edge profile (deleting C:\Users\%username%\AppData\Local\Microsoft\Edge\User Data\Default
) solves the problem.
Usually, this is not a problem, but the loss of the bookmarks is of course not pleasant.
The good thing is, we know it’s related to the profile. We don’t need to troubleshoot anything at the machine level or look at registry keys. The problem is somewhere in the profile.
Process Monitor
I created a process monitor log and stopped recording when the title bar froze. I filtered to msedge.exe and counted the results:
Lots of events. ACCESS DENIED
is always interesting to me. But what do we know until now? Only file activity is interested and something inside C:\users\%username%\AppData\Local\Microsoft\Edge\User Data
. So we filter our Log further.
No ACCESS DENIED
and some others disappears. To sum up, everything seems okayish. No further hints here.
Capture a memory dump
I thought it’s a good idea to capture a memory dump. Because the title bar says “not responding”, I captured a memory dump with: procdump -ma {procid}
.
We load the .dmp
file into WinDbg.
~
into the WinDbg. In my case the memory dump had 45 threads.You have to know that most threads are WorkerThreads waiting for work. We don’t need to check these.
A characteristic property of these WorkerThreads are there length. They’re usually short (depth is about ~8).
An amazing way is to use the PDE extension by Andrew Richards.
You can load the extension
.load C:\path\x64\winext\PDE.dll
.After that you can run:
!deep 15
. The command will prompt all call stacks with a depth 15 or higher.Now we want to check the stack:
0:000> k
# Child-SP RetAddr Call Site
00 000000fd`b5bfd5b0 00007ffd`d1fd189b msedge!std::Cr::__tree<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> >,std::Cr::less<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > >,std::Cr::allocator<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > > >::__find_equal<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > >+0xa2
01 000000fd`b5bfd620 00007ffd`d1fd1694 msedge!std::Cr::__tree<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> >,std::Cr::less<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > >,std::Cr::allocator<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > > >::__find_equal<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > >+0x17f
02 000000fd`b5bfd6a0 00007ffd`d2e44eb8 msedge!std::Cr::__tree<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> >,std::Cr::less<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > >,std::Cr::allocator<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > > >::__emplace_hint_unique_key_args<std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> >,std::Cr::basic_string<char16_t,std::Cr::char_traits<char16_t>,std::Cr::allocator<char16_t> > const & __ptr64>+0x50
03 000000fd`b5bfd710 00007ffd`d2e44618 msedge!autofill::AutofillProfileComparator::GetNamePartVariants+0x480
04 000000fd`b5bfd8c0 00007ffd`d2e43fd8 msedge!autofill::AutofillProfileComparator::IsNameVariantOf+0xaa
05 000000fd`b5bfdae0 00007ffd`d2e43910 msedge!autofill::AutofillProfileComparator::HaveMergeableNames+0x298
06 000000fd`b5bfdc20 00007ffd`d2e3aec5 msedge!autofill::AutofillProfileComparator::AreMergeable+0x8e
07 000000fd`b5bfdc60 00007ffd`ccddac54 msedge!autofill::PersonalDataManagerCleaner::DedupeProfiles+0x1fd
08 000000fd`b5bfdd60 00007ffd`ccdd7ced msedge!autofill::PersonalDataManagerCleaner::ApplyDedupingRoutine+0x1e8
09 000000fd`b5bfdea0 00007ffd`ccdd7c40 msedge!autofill::PersonalDataManagerCleaner::ApplyAddressFixesAndCleanups+0x15
0a 000000fd`b5bfded0 00007ffd`ccdd90c0 msedge!autofill::PersonalDataManagerCleaner::CleanupDataAndNotifyPersonalDataObservers+0x120
0b 000000fd`b5bfdf40 00007ffd`ccdd8a1c msedge!autofill::AlternativeStateNameMapUpdater::LoadStatesData+0xcc
0c 000000fd`b5bfe070 00007ffd`ccdd7c02 msedge!autofill::AlternativeStateNameMapUpdater::PopulateAlternativeStateNameMap+0xd0
0d 000000fd`b5bfe220 00007ffd`ccdd6eec msedge!autofill::PersonalDataManagerCleaner::CleanupDataAndNotifyPersonalDataObservers+0xe2
0e 000000fd`b5bfe290 00007ffd`cc918780 msedge!autofill::PersonalDataManager::OnWebDataServiceRequestDone+0x43c
0f 000000fd`b5bfe390 00007ffd`cdf911e7 msedge!WebDataRequestManager::RequestCompletedOnThread+0x70
10 000000fd`b5bfe3e0 00007ffd`cdfc8142 msedge!base::internal::Invoker<base::internal::BindState<void (WebDataRequestManager::*)(std::Cr::unique_ptr<WebDataRequest,std::Cr::default_delete<WebDataRequest> >, std::Cr::unique_ptr<WDTypedResult,std::Cr::default_delete<WDTypedResult> >),scoped_refptr<WebDataRequestManager>,std::Cr::unique_ptr<WebDataRequest,std::Cr::default_delete<WebDataRequest> >,std::Cr::unique_ptr<WDTypedResult,std::Cr::default_delete<WDTypedResult> > >,void ()>::RunOnce+0x47
11 000000fd`b5bfe420 00007ffd`ca23669f msedge!base::TaskAnnotator::RunTaskImpl+0x122
12 000000fd`b5bfe560 00007ffd`ca782a81 msedge!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl+0x58f
13 000000fd`b5bfe870 00007ffd`cbaca689 msedge!base::MessagePumpForUI::DoRunLoop+0xcc1
14 000000fd`b5bfea40 00007ffd`cc403cfe msedge!base::MessagePumpWin::Run+0x79
15 000000fd`b5bfeaa0 00007ffd`cc40b2ac msedge!base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run+0x11e
16 000000fd`b5bfeb50 00007ffd`cc2e98f0 msedge!base::RunLoop::Run+0xfc
17 000000fd`b5bfec50 00007ffd`cc2e95cc msedge!content::BrowserMainLoop::RunMainMessageLoop+0x9a
18 000000fd`b5bfecc0 00007ffd`cc2e8caa msedge!content::BrowserMain+0xa4
19 000000fd`b5bfed70 00007ffd`cc2e7e42 msedge!content::RunBrowserProcessMain+0xe0
1a 000000fd`b5bfee90 00007ffd`cc2a651e msedge!content::ContentMainRunnerImpl::RunBrowser+0x46e
1b 000000fd`b5bfeff0 00007ffd`cc1cf536 msedge!content::ContentMainRunnerImpl::Run+0x31e
1c 000000fd`b5bff140 00007ffd`cc1ce2f4 msedge!content::RunContentProcess+0x2e3
1d 000000fd`b5bff360 00007ffd`cc1cd6be msedge!content::ContentMain+0x64
1e 000000fd`b5bff3f0 00007ff6`2ff25626 msedge!ChromeMain+0x27e
1f 000000fd`b5bff710 00007ff6`30013be2 msedge_exe!MainDllLoader::Launch+0x386
20 000000fd`b5bff9a0 00007ff6`2ffceca2 msedge_exe!wWinMain+0xf2c
21 000000fd`b5bffec0 00007ffe`4a2384d4 msedge_exe!__scrt_common_main_seh+0x106
22 000000fd`b5bfff00 00007ffe`4a9a1791 kernel32!BaseThreadInitThunk+0x14
23 000000fd`b5bfff30 00000000`00000000 ntdll!RtlUserThreadStart+0x21
You have to read the stack from bottom to top. The first few lines seem the normal “startup”-routine. The part seems interesting:
03 000000fd`b5bfd710 00007ffd`d2e44618 msedge!autofill::AutofillProfileComparator::GetNamePartVariants+0x480
04 000000fd`b5bfd8c0 00007ffd`d2e43fd8 msedge!autofill::AutofillProfileComparator::IsNameVariantOf+0xaa
05 000000fd`b5bfdae0 00007ffd`d2e43910 msedge!autofill::AutofillProfileComparator::HaveMergeableNames+0x298
06 000000fd`b5bfdc20 00007ffd`d2e3aec5 msedge!autofill::AutofillProfileComparator::AreMergeable+0x8e
07 000000fd`b5bfdc60 00007ffd`ccddac54 msedge!autofill::PersonalDataManagerCleaner::DedupeProfiles+0x1fd
08 000000fd`b5bfdd60 00007ffd`ccdd7ced msedge!autofill::PersonalDataManagerCleaner::ApplyDedupingRoutine+0x1e8
09 000000fd`b5bfdea0 00007ffd`ccdd7c40 msedge!autofill::PersonalDataManagerCleaner::ApplyAddressFixesAndCleanups+0x15
0a 000000fd`b5bfded0 00007ffd`ccdd90c0 msedge!autofill::PersonalDataManagerCleaner::CleanupDataAndNotifyPersonalDataObservers+0x120
0b 000000fd`b5bfdf40 00007ffd`ccdd8a1c msedge!autofill::AlternativeStateNameMapUpdater::LoadStatesData+0xcc
0c 000000fd`b5bfe070 00007ffd`ccdd7c02 msedge!autofill::AlternativeStateNameMapUpdater::PopulateAlternativeStateNameMap+0xd0
0d 000000fd`b5bfe220 00007ffd`ccdd6eec msedge!autofill::PersonalDataManagerCleaner::CleanupDataAndNotifyPersonalDataObservers+0xe2
0e 000000fd`b5bfe290 00007ffd`cc918780 msedge!autofill::PersonalDataManager::OnWebDataServiceRequestDone+0x43c
0f 000000fd`b5bfe390 00007ffd`cdf911e7 msedge!WebDataRequestManager::RequestCompletedOnThread+0x70
The WebDataRequestManager
leads to all the autofill
stuff. I captured a memory dump a few seconds later, and we see the same stack.
You can google some functions and learn a bit about what things do (without reading the source code).
Okay, what can we say right now? It seems that the stack is related to Autofill. And we also know, that there is some “corrupt” file in our browser profile.
A next search on the internet could be: “chromium autofill file location” and we would then find the following superuser.com article.
We learn that the “autofill file” is {AppData}\Microsoft\Edge\User Data\Default\Web Data
. Interesting.
I’m not going to lie, it wasn’t like that … and I used another tool to find the file.
Windows Performance Analyzer
Because ProcMon leads to nowhere, I thought a ETL trace would be a good idea. You can use the Windows Performance Recorder or UIforETW. After I captured the needed .ETL file, I opened it with Windows Performance Analyzer - you can get it via Microsoft Store.
We see something we would expect. Usually something like that is called CPU saturation
and in our case one core is working hard for msedge.exe (100/16 = 6,25).
Wee see that the stack traces contains all these autofill stuff, we already know from the memory dump. But we want the file.
Disk usage window
We take the disk usage to our analysis window and select Utilization by Process, Path Name, Stack
.
Interesting our friend Web Data
is back. No completion time, so it’s still a outstanding file access.
When we delete the file, MS Edge opens again without hangs.
Final words
We could find the problematic file relatively easily. ProcMon didn’t help but WinDbg had the right hints and WPA showed the relevant file.
The issue itself was a little bit odd. Sometimes I restored the old Web Data (for repro) .. but it worked. I had also a case, when I waited very long (>1h?) it repaired itself and worked again.
I could have found the solution much quicker with WinDbg or WPA or another tool? Let me know!
Happy troubleshooting.