From: Oleg Starodumov on
>> Yes, the performance hit is coming from dispatching debug events to
>> the debugger.
>> So if the application generates lots of events (usually exceptions,
>> also debug output, module load/unload, thread start/exit, etc.), it
>> can be slowed down. If there is not too many debug events,
>> performance will not be seriously affected.
>
> Ok. In the "normal program flow" there shall be not too many of them. How are the calls serialized between the
> debuggee and the debugger? Over shared memory?
>

There is a debug port the debugger is listening on. When a debug event occurs,
a message will be delivered to that port. While the message is being delivered
and the debugger processes it, the debuggee is suspended. I am not sure that
I understand all the details of this process (I am not a kernel expert and can
be wrong), but the main point here is that delivery of debug events requires
thread context switch, which affects performance the most, even if
the debugger itself processes the event quickly.

> When I do nothing within the most event-procedures (only unhandled exceptions will be processed) is it possible to say
> how much overhead it will be?

IMO the best way would be to measure how your application works
under debugger (use a custom debugger, or WinDbg, which also processes
debug events very quickly (unlike VS debugger)).

I did some tests in the past and found that on an application that raises
lots of exceptions the performance hit was very significant (several times slower
for that particular application). But for most normal applications there should
be no significant slowdown.

> Is it possible to subscribe to the needed event(s) only?

No.

> Mode "Fast": It creates a thread which waits for an event to be set until it calls "MiniDumpCreateDump" in process.
> The event will be set from the custom unhandled exception filter.
>
> Mode "Safe": It starts an watchdog-process (actually rundll32.exe with an exported "DebuggerMain" from my dll (by
> using rundll32 I must not deploy anything else but the dll), which attaches to the application as a Debugger, and
> calls "MiniDumpCreateDump" within the watchdog process.
>
> I will forget about the third method (creating a debugger-process within the unhandled exception filter which creates
> the Minidump) because according to your posting it is not any safer than the "Fast" mode.
>
> What do you think about it?
>

I think it should be OK.

Oleg




From: Oleg Starodumov on

>> Mode "Fast": It creates a thread which waits for an event to be set until
>> it calls "MiniDumpCreateDump" in process. The event will be set from the custom unhandled exception filter.
>
> My worry here would be that the process might die before the other thread gets scheduled. Your unhandled exception
> filter will have to wait on the other thread somehow.
>

Yes, it has to signal and wait (usually using two events as you have later described).

Oleg



From: Oleg Starodumov on
> > HeapDestroy could have undesirable side effects if the heap header is corrupted.
> > IMO a much safer option would be to reserve a range of virtual memory
> > beforehand, and release it before calling the filter.
>
> I guess you mean reseve + commit VM.
>

No, I meant only reserve.

> I do not really care about memory corruption, because I consider it as unrecoverable. The heap header could be
> corrupted yes, but my pointer returned by VirtualAlloc could be altered too. You may say that the risk of accidentally
> modifying this little pointer is lower than modifying the big heap header,

And the consequences of modifying this little pointer are much less serious, too :)

> but I consider that both cases are unlikely to occur within my software :-)

Absolutely agree, seriously :)
IMO with proper approach to SW testing we can eliminate most of the situations
that can lead to really bad corruptions. That's why I still think that creating minidumps
in process is an acceptable solution.

> However, there are specific errors that I am interested in catching and reporting, and for which writing a unhandled
> exception filter is difficult:
> - stack overflow
> - out of memory
> For the first one, Jochen gave me an acceptable solution. The second is a very difficult one, as I need memory to
> report the error, but I don't have that memory. So, how can I increase the chance to have sufficient memory for at
> least writing a mini dump ?
>
> I first had the same idea as yours : allocate memory beforehand, and free it before calling MiniDumpWriteDump. Once
> you have decided how much memory to reserve (not a so easy question to answer),

Exactly.

> this only solves the case when the memory limit has been filled by your process. Since its execution is suspended as
> we are in a filter, the reserved memory that you just freed should still be available afterward. Okay.
>

I considered only this case.

> But what happens if the memory is widely allocated by an other process which asks for memory faster than you can
> release it ? In such a case, you have to free a lot of memory in order to increase your chance to successfully report
> the bad_alloc failure. I can see two ways of doing it :
> - reserve beforehand a lot of memory (the problem of how much to reserve still has to be solved) and free it when you
> need it
> - force your process to release as much memory as it is possible to do by destroying the CRT heap
>

Are you sure that your CRT heap will be big enough?

Are you sure that the other process is allocating memory not fast enough
to outperform HeapDestroy? And MiniDumpWriteDump after that?

And what is the use of minidump in this case? What extra information
will you get from it, if the reason of the problem is in an external process?

> Sorry for this so brief reply, next time I will not forget to give detailed infos about the origin and the creation of
> the universe :-)
>

It was "brief" but interesting.

Oleg



From: Skywing [MVP] on
I would recommend the rundll32 option. I have done something very similar
before for a product that I worked on (and in fact also used rundll32 for
this purpose). There are a couple of gotchas to consider:

- I would try to make most of the state relating to how to communicate with
the watchdog process readonly after initialization to maximize the chance
that it won't be overwritten and later prevent a successful error reporting
run.
- Make sure you do *all* memory allocations up-front at startup. Never ever
touch the heap (even a private heap!) from your unhandled exception handler.
- Specific to rundll32, make sure that you dispatch window messages in the
watchdog process on the thread that rundll32 calls in to you with.
Evidently, rundll32 likes to create a hidden window, for whatever reason,
and if you don't dispatch window messages, I have found that this results in
a couple of programs getting upset when broadcasting of messages doesn't
work as they would expect. (Stupid and undocumented, but it caused problems
for us a couple of times until I just added a dummy message loop.)

Going with the watchdog process approach does not have the performance hit
of a debugger process, and it also does not prevent you from attaching a
debugger later on. It is ever so slightly less robust than a watchdog
process acting as a full debugger, but if you are careful (and make all of
your state immutable after initialization), it's very close to the debugger
option (and with much less overhead and performance hit - every exception,
module load event, and soforth will not cause the entire process to be
suspended while the debugger watchdog inspects the debug event).

--

Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
"G�nter Prossliner" <g.prossliner/gmx/at> wrote in message
news:%23fUlrG9DHHA.3596(a)TK2MSFTNGP03.phx.gbl...
> Hello Oleg!
>
>
> Thank you for your informative answer!
>
>>> Maybe you can answer me the following question too:
>>> If Method C will be implemented, how much performance does it cost?
>>> And one which operations? Where does the performance - degradation
>>> come from? The Debugger-Events?
>>>
>>
>> Yes, the performance hit is coming from dispatching debug events to
>> the debugger.
>> So if the application generates lots of events (usually exceptions,
>> also debug output, module load/unload, thread start/exit, etc.), it
>> can be slowed down. If there is not too many debug events,
>> performance will not be seriously affected.
>
> Ok. In the "normal program flow" there shall be not too many of them. How
> are the calls serialized between the debuggee and the debugger? Over
> shared memory?
>
> When I do nothing within the most event-procedures (only unhandled
> exceptions will be processed) is it possible to say how much overhead it
> will be? Is it possible to subscribe to the needed event(s) only?
>
>> This is if you attach debugger to an already running application. If
>> you start the app under debugger (which you shouldn't do IMO), there
>> will be lots of various debug checks enabled by default (heap, etc.),
>> which will hurt performance too.
>
> The application will not be started under the debugger.
>
>>> Ok. If I understand this correctly, choosing the method will not be
>>> any safer than creating a Thread in-process which creates the dump
>>> (new Process vs. new Thread).
>>>
>>
>> Yes, though creating a new thread from the filter is not a good idea
>> IMO,
>> I would better recommend to create the helper thread beforehand, then
>> the failing thread would only need to set one event and wait for
>> another -
>> same as with external watchdog.
>
> This is a very good idea! I will go on with that.
>
>
> I will implement the following methods:
>
> You can configure the DumpHelper by using two modes:
>
> Mode "Fast": It creates a thread which waits for an event to be set until
> it calls "MiniDumpCreateDump" in process. The event will be set from the
> custom unhandled exception filter.
>
> Mode "Safe": It starts an watchdog-process (actually rundll32.exe with an
> exported "DebuggerMain" from my dll (by using rundll32 I must not deploy
> anything else but the dll), which attaches to the application as a
> Debugger, and calls "MiniDumpCreateDump" within the watchdog process.
>
> I will forget about the third method (creating a debugger-process within
> the unhandled exception filter which creates the Minidump) because
> according to your posting it is not any safer than the "Fast" mode.
>
> What do you think about it?
>
>
> GP
>

From: Skywing [MVP] on
I would tend to prefer inheritance (or handle duplication) of unnamed
objects to named objects whereever possible. You don't have to worry about
the security implications of someone malicious opening your named object and
doing bad things to it, and you don't create a headache for yourself if you
later decide to support multiple instances of your application running on
the same TS session.

--

Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
"Ben Voigt" <rbv(a)nospam.nospam> wrote in message
news:%23rSF7p%23DHHA.3396(a)TK2MSFTNGP02.phx.gbl...
>
> "Aurelien Regat-Barrel" <nospam.aregatba(a)yahoo.fr.invalid> wrote in
> message news:O1RfBc%23DHHA.3524(a)TK2MSFTNGP06.phx.gbl...
>> Hi Ben,
>>
>> Ben Voigt a �crit :
>>> A better version of option 3 is to combine the other two solutions. Run
>>> your watchdog process all the time, but wait for an event before
>>> attaching the debugger. The problem of keeping the process alive until
>>> the watchdog wakes is still present.
>>
>> By starting the watchdog as a child process, you could make it to inherit
>> a kernel object (an event for example) to set once it is ready ?
>
> Named events can be used for communication between processes. You might
> need one event set by the exception handler "APPNAME_BEGINDUMP" and one
> set by the watchdog "APPNAME_DUMPCOMPLETE"
>
>>
>> --
>> Aur�lien Regat-Barrel
>
>