D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 8936 - Throwing results in searching the whole directory tree rooted in current directory
Summary: Throwing results in searching the whole directory tree rooted in current dire...
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: druntime (show other issues)
Version: D2
Hardware: All Windows
: P1 regression
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-11-02 07:11 UTC by Denis Shelomovskii
Modified: 2013-02-10 10:21 UTC (History)
6 users (show)

See Also:


Attachments
procmon (316.66 KB, application/octet-stream)
2012-12-23 06:48 UTC, Andrej Mitrovic
Details

Note You need to log in before you can comment on or make changes to this issue.
Description Denis Shelomovskii 2012-11-02 07:11:54 UTC
This is catastrophic Windows druntime issue.

Triggering code:
---
void main()
{
    throw new Exception("Ex"); // or Error, or any Throwable
    // try throw new Exception("Ex"); catch { } // same here
}
---

Want something really long? Lunch this on Windows:
---
import std.file;

void main()
{
    chdir(`C:\`);
    try
        // Let's serach the whole C: drive!
        throw new Exception("Ex");
    catch { }
}
---

Since dmd 2.060.
Comment 1 Alex Rønne Petersen 2012-11-02 07:13:50 UTC
I don't have a Windows machine available. Do you know where in druntime this search is being triggered?

This is...kind of bad.
Comment 2 Andrej Mitrovic 2012-11-02 07:18:59 UTC
My best bet is that new dbghelp.dll code which tries to find dbghelp.dll is causing the search.
Comment 3 Denis Shelomovskii 2012-11-02 07:33:05 UTC
Call stack (thanks OllyDbg):
---
Address    Stack      Procedure / arguments
0012E578   7C90D77A   Includes ntdll.KiFastSystemCallRet
0012E57C   7C80ED62   ntdll.ZwQueryDirectoryFile
0012E888   7C8138B7   kernel32.FindFirstFileExW
0012EB1C   59C7117B   kernel32.FindFirstFileA
0012EB20   0012EE90     FileName = ".\D\dmd2.055\html\d\*.*"
0012EB24   0012EC4C     pFindFileData = 0012EC4C
0012EF9C   59C71636   dbghelp.59C7109F
0012F110   59C717C6   ? dbghelp.59C7149F
0012F15C   59C71839   ? dbghelp.59C716F4
0012F17C   59C7B424   ? dbghelp.FindExecutableImageEx
0012F1C0   59C816F7   ? dbghelp.59C7B2D1
0012F32C   59C820BF   dbghelp.59C81652
0012F33C   59C82109   dbghelp.59C82061
0012F37C   59C75332   ? dbghelp.59C820D5
0012F3B0   59C84B93   dbghelp.59C75309
0012F408   59C84CC4   dbghelp.59C84B53
0012F4B4   59C8530F   dbghelp.59C84C5E
0012F4DC   59C8356D   dbghelp.59C852DF
0012F514   00421AF0   Includes dbghelp.59C8356D
0012FDA4   004219B3   test_d2.00421A0C
0012FDD0   0042178D   test_d2.00421974
0012FDDC   004171F4   test_d2.00421778
0012FDEC   0041A546   test_d2.004171E0
0012FDF0   00410CEC   test_d2.0041A530
0012FE08   0040B9FD   test_d2.00410CC4
0012FE18   004082D4   test_d2.0040B9F0
0012FE20   00402082   test_d2.004082C8
0012FE54   0040823A   test_d2.00402010
0012FE68   00407EBC   test_d2.00408228
0012FE98   0040827D   test_d2.00407E54
0012FEAC   00407EBC   test_d2.00408248
0012FEDC   00407E40   test_d2.00407E54
0012FF84   00435311   test_d2.00407BF4
0012FF88   00000001     Arg1 = 00000001
0012FF8C   009303C4     Arg2 = 009303C4
0012FF90   00930400     Arg3 = 00930400
0012FF94   00000000     Arg4 = 00000000
0012FFC4   7C817077   Includes test_d2.00435311
---

`FileName` goes through the whole disk.
Comment 4 Walter Bright 2012-11-13 22:39:47 UTC
Any idea what file it's looking for?
Comment 5 Denis Shelomovskii 2012-11-14 01:49:12 UTC
(In reply to comment #4)
> Any idea what file it's looking for?

Launching "throw-C-release.exe" with code from the second example from description:

Call stack of main thread
Address    Stack      Procedure / arguments                                              Called from                   Frame
Call stack of main thread
Address    Stack      Procedure / arguments                                              Called from                   Frame
0012D540   7C90D5AA   Includes ntdll.KiFastSystemCallRet                                 ntdll.7C90D5A8                0012D838
0012D544   7C80EC96   Includes ntdll.7C90D5AA                                            kernel32.7C80EC94             0012D838
0012D83C   7C8138B7   kernel32.FindFirstFileExW                                          kernel32.7C8138B2             0012D838
0012DAD0   59C7117B   kernel32.FindFirstFileA                                            dbghelp.59C71175              0012DACC
0012DAD4   0012DE44     FileName = ".\Documents and Settings\Denis\Local Settings\Temp\
0012DAD8   0012DC00     pFindFileData = 0012DC00
0012DF50   59C71636   dbghelp.59C7109F                                                   dbghelp.59C71631              0012DF4C
0012E0C4   59C717C6   ? dbghelp.59C7149F                                                 dbghelp.59C717C1              0012E0C0
0012E110   59C71839   ? dbghelp.59C716F4                                                 dbghelp.59C71834              0012E10C
0012E114   00B27E68     Arg1 = 00B27E68 ASCII "throw-C-release.exe"
0012E118   00B7FEA0     Arg2 = 00B7FEA0
0012E11C   00B27772     Arg3 = 00B27772 ASCII "C:\throw-C-release.exe"
0012E120   59C7ABE7     Arg4 = 59C7ABE7
0012E124   00B27748     Arg5 = 00B27748
0012E128   00000000     Arg6 = 00000000
0012E130   59C7B424   ? dbghelp.FindExecutableImageEx                                    dbghelp.59C7B41F              0012E12C
0012E134   00B27E68     Arg1 = 00B27E68 ASCII "throw-C-release.exe"
0012E138   00B7FEA0     Arg2 = 00B7FEA0
0012E13C   00B27772     Arg3 = 00B27772 ASCII "C:\throw-C-release.exe"
0012E140   59C7ABE7     Arg4 = 59C7ABE7
0012E144   00B27748     Arg5 = 00B27748
0012E174   59C816F7   ? dbghelp.59C7B2D1
<same as in comment 3>

MSDN about FindExecutableImageEx function:
http://msdn.microsoft.com/ru-ru/library/windows/desktop/ms679343(v=vs.85).aspx

P.S.
Common, OllyDbg if free and easy to use. And probably not the only available debugger. Everybody can do the same himself.
Comment 6 Andrej Mitrovic 2012-11-14 17:24:53 UTC
Just a guess, but maybe caused by one of these (since they deal with dbghelp.dll):

https://github.com/D-Programming-Language/druntime/pull/243
https://github.com/D-Programming-Language/druntime/pull/225

It's damn hard to find matching DMD+druntime+phobos versions that compile together for that pull so I can't test these out.
Comment 7 Walter Bright 2012-11-14 18:50:51 UTC
(In reply to comment #6)
> It's damn hard to find matching DMD+druntime+phobos versions that compile
> together for that pull so I can't test these out.

Just use the latest versions of everything, but the older version of the stack trace code.
Comment 8 David Held 2012-11-22 02:54:27 UTC
The root cause is that druntime/core/sys/windows/stacktrace.d::static this() calls WinAPI's SymInitialize() with a NULL user path.  This results in the default path:

  %CWD%;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%

as per the MSDN documentation here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681351%28v=vs.85%29.aspx.  Unfortunately, I cannot repro this behavior on Windows 7 Home Premium SP1, dbghelp.dll 6.1.  I suspect that newer versions of dbghelp.dll are simply more clever than what MSDN states (for instance, if the semantics were changed to make the default path start with the image location, 99% of all directory scanning would be eliminated; also, it is pretty silly to not have this as the default behavior).

Please report which version of dbghelp.dll you are using.  There are likely multiple versions present on your machine, so you can discover the one being used via 'where':

  where dbghelp.dll

It will most likely discover the version in %SystemRoot%\system32.  You can find the version in the file properties.

Assuming that this is truly only a problem with older versions of dbghelp.dll (e.g.: 5.x versions), it is not difficult to simply provide a custom user path starting with the current executable image path.  However, I do not have a means to verify the fix, as I cannot repro the actual problem.
Comment 9 Benjamin Thaut 2012-12-07 09:37:27 UTC
I don't quite understand the issue here. Why is it a problem that is searches for appropriate .pdb files?
Comment 10 Denis Shelomovskii 2012-12-07 10:54:25 UTC
(In reply to comment #9)
> I don't quite understand the issue here. Why is it a problem that is searches
> for appropriate .pdb files?

Because the search may require hours for every thrown (cached or not) exception (even in release build).
Comment 11 Benjamin Thaut 2012-12-07 11:42:05 UTC
(In reply to comment #10)
> (In reply to comment #9)
> > I don't quite understand the issue here. Why is it a problem that is searches
> > for appropriate .pdb files?
> 
> Because the search may require hours for every thrown (cached or not) exception
> (even in release build).

Are you sure? It should only search for the appropriate pdbs on the first throw.
Comment 12 Andrej Mitrovic 2012-12-07 12:55:19 UTC
(In reply to comment #11)
> (In reply to comment #10)
> > (In reply to comment #9)
> > > I don't quite understand the issue here. Why is it a problem that is searches
> > > for appropriate .pdb files?
> > 
> > Because the search may require hours for every thrown (cached or not) exception
> > (even in release build).
> 
> Are you sure? It should only search for the appropriate pdbs on the first
> throw.

Yes we're sure. I can personally hear it scraping my hard drive for a dozen seconds before I get a stack trace.
Comment 13 Benjamin Thaut 2012-12-07 13:51:43 UTC
I have a improved version of the stacktrace class at:

https://github.com/Ingrater/druntime/blob/master/src/core/sys/windows/stacktrace.d

It's more similar to the unix interface as you can first query a list of addresses and then resolve it later. This might fix the issue as the resolving of the symbols could be delayed until it actually needs to be printed instead resolving at throw time. I'm also no longer calling SymInitialize with NULL, so this should fix the other issue too.

I wanted to do a pull request for this soon, but I currently don't have time for it. So if it is super critical someone else might want to do it. 

All the version(NOGCSAFE){...} parts can just be removed from the file.
Comment 14 Benjamin Thaut 2012-12-08 01:45:46 UTC
This commit most likely broke things:

https://github.com/D-Programming-Language/druntime/commit/939da7743126c773636a721a33288ac9a92c641f
Comment 15 Benjamin Thaut 2012-12-23 06:33:47 UTC
I can not reproduce this. I even tried it on a windows XP machine with a very old version of dbghelp. What system did you run this on? Please post the version numbers of your dbghelp.dll and imagehlp.dll (in your Windows/System folder or Windows/sysWOW64 if you are using a x64 windows)

Kind Regards
Benjamin Thaut
Comment 16 Andrej Mitrovic 2012-12-23 06:48:59 UTC
Created attachment 1171 [details]
procmon
Comment 17 Andrej Mitrovic 2012-12-23 06:49:31 UTC
(In reply to comment #15)
> I can not reproduce this. I even tried it on a windows XP machine with a very
> old version of dbghelp. What system did you run this on? Please post the
> version numbers of your dbghelp.dll and imagehlp.dll (in your Windows/System
> folder or Windows/sysWOW64 if you are using a x64 windows)
> 
> Kind Regards
> Benjamin Thaut

---
import std.file;

void main()
{
    chdir(`C:\`);
    try
        // Let's serach the whole C: drive!
        throw new Exception("Ex");
    catch { }
}
---

I've added just a partial log of sysinternals process monitor with a filter on 'test.exe' from the above example.
Comment 18 Andrej Mitrovic 2012-12-23 14:48:55 UTC
(In reply to comment #17)
> Hi,
> did you use druntime version 2.060 to reproduce the issue or did you use the
> latest druntime from the git master branch?
> If you used the 2.060 version I think I know where the issue is.

git-head with git-druntime.

However I can recreate it with 2.060 dmd+druntime.
Comment 19 Benjamin Thaut 2012-12-23 15:19:25 UTC
I have a possible fix at:
https://github.com/Ingrater/druntime/tree/pull8936

As I can't reproduce the issue, I can't tell if this actually fixes the issue.
It would be great if someone who can reproduce this, could check the fix and report the results.

Kind Regards
Benjamin Thaut
Comment 20 Andrej Mitrovic 2012-12-23 15:22:56 UTC
(In reply to comment #19)
> I have a possible fix at:
> https://github.com/Ingrater/druntime/tree/pull8936
> 
> As I can't reproduce the issue, I can't tell if this actually fixes the issue.
> It would be great if someone who can reproduce this, could check the fix and
> report the results.
> 
> Kind Regards
> Benjamin Thaut

I've just tried it, same results as before.
Comment 21 Benjamin Thaut 2012-12-23 15:27:12 UTC
Could you compile the debug(PRINTF) version and post which search path is printed to the console?
And with same results you mean it is still searching your whole C drive?

Kind Regards
Benjamin Thaut
Comment 22 Andrej Mitrovic 2012-12-23 15:30:29 UTC
(In reply to comment #21)
> Could you compile the debug(PRINTF) version and post which search path is
> printed to the console?

Search paths: C:;C:\WINDOWS;

> And with same results you mean it is still searching your whole C drive?

Yes.
Comment 23 Benjamin Thaut 2012-12-23 15:34:50 UTC
Where is your binary located? If you put it directly into the C:\ root then it obviously will have to search the whole C drive for pdbs.

Kind Regards
Benjamin Thaut
Comment 24 Andrej Mitrovic 2012-12-23 15:37:20 UTC
(In reply to comment #23)
> Where is your binary located? If you put it directly into the C:\ root then it
> obviously will have to search the whole C drive for pdbs.
> 
> Kind Regards
> Benjamin Thaut

Why does it obviously have to search the entire drive? It doesn't do that in 2.059 and I get a nice stack trace. The whole point of that test-case is that the path the executable is located in is needlessly search for.
Comment 25 Benjamin Thaut 2012-12-23 15:40:36 UTC
(In reply to comment #24)
> Why does it obviously have to search the entire drive? It doesn't do that in
> 2.059 and I get a nice stack trace. The whole point of that test-case is that
> the path the executable is located in is needlessly search for.

Because the documentation says so:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681351%28v=vs.85%29.aspx

I also finally understood the issue. Thanks for your help. I have a fix now and will open a pull request soon.
Comment 26 Benjamin Thaut 2012-12-23 15:45:28 UTC
(In reply to comment #24)

I just commited a fix to https://github.com/Ingrater/druntime/tree/pull8936
can you please confirm it actuall works?

Kind Regards
Benjamin Thaut
Comment 27 Andrej Mitrovic 2012-12-23 15:50:27 UTC
(In reply to comment #26)
> (In reply to comment #24)
> 
> I just commited a fix to https://github.com/Ingrater/druntime/tree/pull8936
> can you please confirm it actuall works?

Yes it works now, and the search path is now:

Search paths: C:\WINDOWS;

Thanks for your work!

Before your latest commit I was going to recommend to try making the code search the Windows folder before it searches the local path. So e.g. in that commit before where I've had:

Search paths: C:;C:\WINDOWS;

maybe the simple fix would be to put the local path last:

Search paths: C:\WINDOWS;C:;
Comment 28 Benjamin Thaut 2012-12-23 15:54:51 UTC
(In reply to comment #27)
> (In reply to comment #26)
> > (In reply to comment #24)
> > 
> > I just commited a fix to https://github.com/Ingrater/druntime/tree/pull8936
> > can you please confirm it actuall works?
> 
> Yes it works now, and the search path is now:
> 
> Search paths: C:\WINDOWS;
> 
> Thanks for your work!
> 
> Before your latest commit I was going to recommend to try making the code
> search the Windows folder before it searches the local path. So e.g. in that
> commit before where I've had:
> 
> Search paths: C:;C:\WINDOWS;
> 
> maybe the simple fix would be to put the local path last:
> 
> Search paths: C:\WINDOWS;C:;

If I understood the documentation correctly the search paths are only for pdbs that are not directly referenced from the executables. For example when you use the microsoft symbol store. Specifying the path of the executable should not be neccessary at all to get correct stack traces.
Comment 29 Andrej Mitrovic 2012-12-23 15:57:38 UTC
(In reply to comment #28)
> If I understood the documentation correctly the search paths are only for pdbs
> that are not directly referenced from the executables. For example when you use
> the microsoft symbol store. Specifying the path of the executable should not be
> neccessary at all to get correct stack traces.

I see. Thanks again for your time!

Could you make this a pull request so we can merge it before 2.061 release?
Comment 31 github-bugzilla 2012-12-25 03:34:04 UTC
Commit pushed to master at https://github.com/D-Programming-Language/druntime

https://github.com/D-Programming-Language/druntime/commit/62f27eb6afebf6927e91203a6d3e00071f6b5b7f
Merge pull request #369 from Ingrater/pull8936

Fix for issue 8936
Comment 32 Martin Nowak 2012-12-25 09:26:20 UTC
I could reproduce this on WindowsXP with the old dbghelp.dll version 5.1.2600.5512.
Comment 34 Alex Rønne Petersen 2013-02-10 10:10:04 UTC
This should be fixed now, yes?
Comment 35 Andrej Mitrovic 2013-02-10 10:21:23 UTC
(In reply to comment #34)
> This should be fixed now, yes?

Yes, fixed in 2.061.