I have DLL and application that will call some function in this dll. For example...
DLL function:
char const* func1()
{
return reinterpret_cast<char const*>(0x11223344);
}
Application code:
func1 = reinterpret_cast<Func1Callback>(::GetProcAddress(hDll, "func1"));
blablabla
char const* ptr = func1();
cout << ptr;
That DLL is not under my control (plugin)..
Same code will cause access violation in my application, so... Is there any mechanism that will allow to determine such errors?
Since the DLL can do anything your program could do the only reliable way is to load it into a separate worker lightweight process and once anything bad happens just restart the process. You'll need some protocol to pass data into the worker process and receive results.
The dll is loaded into your process address space. If it accesses some invalid memory location your process will crash. I don't see any way around it other than not using this dll at all.
If a DLL is returning junk memory addresses to your application, I'd say you shouldn't be using it, because it isn't performing its intended/desired function.
Also, don't try to guard against it by using the Win32 IsBad*Ptr class of functions, as the MSDN documentation states (see also this post by Raymond Chen for a good description of why not).
You can enclose function call into try catch block, it'll help not to crush entire application right at function call, but nobody can garantee, that dll loaded will not alter memory somwhere in your code, in this case yo'll get hard to debug crash in other place. So you can probably raise some protection for just access violation, but anyway cannot fully protext you application for some side effects.
Related
We're on Windows and we want to get a crash dump (possibly using MiniDumpWriteDump) for all scenarios where our application exit's unexpectedly.
So far we have identified, and set up, the following:
SetUnhandledExceptionFilter for unhandled exception (Win32 as well as "normal" C++ ones.)
_set_invalid_parameter_handler for the CRT invalid argument handling
_set_abort_behaviorplus a SIGABRT handler to account for calls to abort()
Is there anything we missed? (Modulo some code non-legitimately calling ExitProcess, TerminateProcess or one of the exit variants.)
I'll note that this question here is orthogonal to how a crash dump is then obtained. E.g., if you want a crash dump in case of abort, you always must use _set_abort_behaviour because otherwise abort just exits.
I'll also note that on Windows7+, not setting SetUHEF and just setting up the "correct" WER dump settings in the registry is often a viable way.
I use exactly the ones you've listed, plus _set_purecall_handler, plus this handy snippet of code:
void EnableCrashingOnCrashes()
{
typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
static const DWORD EXCEPTION_SWALLOWING = 0x1;
const HMODULE kernel32 = LoadLibraryA("kernel32.dll");
const tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
const tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
if(pGetPolicy && pSetPolicy)
{
DWORD dwFlags;
if(pGetPolicy(&dwFlags))
{
// Turn off the filter
pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
}
}
}
Source:
http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/
These other articles on his site also helped me understand this:
http://randomascii.wordpress.com/2011/12/07/increased-reliability-through-more-crashes/
http://randomascii.wordpress.com/2012/07/22/more-adventures-in-failing-to-crash-properly/
SetUnhandledExceptionFilter is emphatically not enough to capture all unexpected exits. If an application accidentally calls a pure virtual function then a dialog will pop up. The application will hang, but not crash. Since there is no exception neither SetUnhandledExceptionFilter nor WER can help. There are a few variations on this theme.
Worse yet is the weirdness if you crash in a kernel callback such as a WindowProc. If this happens in a 32-bit application on 64-bit Windows then the exception is caught by the OS and execution continues. Yes, the crash is silently handed. I find that terrifying.
http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesnt-work/ should detail all of the tricks needed to handle these unusual cases.
To expand on all the answers here's what I found to work best for 100M+ installs:
SetErrorMode to prevent any WER dialogs showing up.
EnableCrashingOnCrashes
PreventSetUnhandledExceptionFilter
SetUnhandledExceptionFilter for system exceptions.
_set_invalid_parameter_handler for the CRT invalid argument handling
_set_abort_behavior plus a SIGABRT handler to account for calls to abort()
std::set_terminate and std::set_unexpected perhaps should also be mentioned.
And the most important part to get it all right:
all these handlers should call a function that executes under a mutex/critical section to ensure that if there are any other crashes happening in other threads at the same time they would all stop and wait instead of causing havoc.
signal handler for SIGABRT must set itself back as a SIGABRT handler! Without this if you get crashes happening at the same time from other threads you process will exit immediately without giving you any time to handle the crash.
actual handling of the error should ideally happen in another process, or at least in another thread that was started at the beginning of the process, otherwise you won't be able to handle low memory conditions or stackoverflow errors.
See setExceptionHandlers below for reference. Also, most likely you don't want to hook up all the handlers in debug builds or when IsDebuggerPresent.
#include <signal.h>
#include <windows.h>
#include <boost/thread/mutex.hpp>
void EnableCrashingOnCrashes();
void PreventSetUnhandledExceptionFilter();
static void exceptionHandler(EXCEPTION_POINTERS* excpInfo)
{
// your code to handle the exception. Ideally it should
// marshal the exception for processing to some other
// thread and waif for the thread to complete the job
}
static boost::mutex unhandledExceptionMx;
static LONG WINAPI unhandledException(EXCEPTION_POINTERS* excpInfo = NULL)
{
boost::mutex::scoped_lock lock(unhandledExceptionMx);
if (!excpInfo == NULL)
{
__try // Generate exception to get proper context in dump
{
RaiseException(EXCEPTION_BREAKPOINT, 0, 0, NULL);
}
__except (exceptionHandler(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER)
{
}
}
else
{
exceptionHandler(excpInfo);
}
return 0;
}
static void invalidParameter(const wchar_t* expr, const wchar_t* func,
const wchar_t* file, unsigned int line, uintptr_t reserved)
{
unhandledException();
}
static void pureVirtualCall()
{
unhandledException();
}
static void sigAbortHandler(int sig)
{
// this is required, otherwise if there is another thread
// simultaneously tries to abort process will be terminated
signal(SIGABRT, sigAbortHandler);
unhandledException();
}
static void setExceptionHandlers()
{
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
SetUnhandledExceptionFilter(unhandledException);
_set_invalid_parameter_handler(invalidParameter);
_set_purecall_handler(pureVirtualCall);
signal(SIGABRT, sigAbortHandler);
_set_abort_behavior(0, 0);
EnableCrashingOnCrashes();
PreventSetUnhandledExceptionFilter();
}
Tall order, just in brief:
You need not to use any other _set* functions, SetUnhandledExceptionFilter is enough for all.
C runtime functions like abort will disable the global exception handler, which you setup using SetUnhandledExceptionFilter. CRT will simply call this same function will NULL parameter, and your exception-handler is disabled (not called), if CRT is causing crash! What you can do? [X]
Disable all other running threads when the excption-handler gets called. Just lookup all threads using CreateToolhelp32Snapshot, and other functions. Look for this process, and suspend all other running threads (except current, ofcourse).
Use SEH or no-SEH, global-exception handler gets called unless CRT interfers. Not to worry (in MOST cases).
Do not any CLR in-between, it will not allow the exception handler to call, if any CLR/managed call (yes from C/C++) comes in between.
You cannot handle one exception - Stack Overflow! Think! Running under a debugger is only solution, see below.
There is more to it, which I haven't tried (not found usefulness) - Vectored Exception Handling.
One other approach is to run the application into a debugger, which you can craft yourself! In the debugger, you can catch ALL exceptions, just like VS debugger catches. See my article. But, you know, this is not proper approach.
EDIT: Just read the last content about process-termination. You shouldn't control that. In any case, you can just hook the required APIs, which would act as what you code for (like displaying message box).
[X] You need to use API hooking. I dont have link and details handy. You'd hook other related APIs, but primarily the SetUnhandledExceptionFilter (after you'd called it for you). You dummy (hooked) function will look like:
xxx SetUnhandledExceptionFilter_DUMMY(xxx)
{
// Dont do any thing
return NULL;
}
I dont have link and details of API hooking handy.
And why not attempt to make your application more safe?
Correct all warnings (yes, even level 4).
Use static analysis. VS itself has (in higher versions, though. Except 2012 - all variants have). Other SA tools are available.
Do careful code-reviewing. It pays!
Run and Debug your RELEASE build from the debugger. Use all features.
Look and correct all possible memory leaks.
Use defensive approach to programming. Rather than checking if null, defend it using ASSERT, or your own assert. Pack it with assertion, log, return from function.
I will add a workaround that one can use in certain scenarios when running on Windows 7:
Windows Error Reporting (WER) offers the option to write full memory dumps on app crash.
So, if you are fine with that, you "just" have to make sure that the crash scenarios you're actually interested in will trigger WER. ... Which, really, leads us back to this very question, but still ...
You can catch any exception with WER. As you have seen the CRT sometimes forces to call WER.
If you want to always catch excpetion in-process, you need to prevent the calling of SetUnhandledExceptionFilter(NULL) from the CRT. For more info see my blog entry: Improved “PreventSetUnhandledExceptionFilter”
I'm calling a function from a DLL, like this:
__declspec ( dllimport ) bool dll_function(...);
int main() {
[...]
if (dll_function(...)) {
[...]
}
}
In some cases, the data I pass to the DLL function will lead to a crash of the DLL. Is it possible to catch this so my application doesn't crash as well (without modifying the DLL which is not created by me)?
You can catch AVs with the __try and __except keywords in the MSVC compiler. Not all that useful, you have no idea what kind of damage was done. The state of your program might well be corrupted. The heap might be blown for example, causing subsequent random failure. Hosting the DLL in its own process and using IPC to talk to it is the only decent approach.
In some cases, the data I pass to the
DLL function will lead to a crash of
the DLL. Is it possible to catch this
so my application doesn't crash as
well?
Isn't it possible to prevent the dll from crashing if you only call the function with valid data? That should be the preferable solution in any case - but its hard to tell without knowing which dll you want to use. But in most cases, you should have an idea what "data" exactly results in an crash...
Try looking at:
http://msdn.microsoft.com/en-us/library/ms680634%28v=vs.85%29.aspx
and
Enforce Filter code by Oleg Starodumov (www.debuginfo.com)
http://www.debuginfo.com/articles/debugfilters.html
However, that is a top level filter and not a try/catch. You can perhaps restart your process.
You might need to use __try for exceptions. Again, probably better to fix the problem or just crash than to try to catch it.
I agree with the others that rather than suppressing or hiding the crash you should fix it. I don't know how well you can recover from the crash - is it going to be useful to continue execution after something like that?
I'm not sure if this is the problem, try specifying the correct calling convention. (__stdcall, __cdecl, etc).
If that's not the problem, we need to see what you are passing to the function and possibly the function code if you have it.
I wrote my own reference counted memory manager c++ (for fun) and I'm sure it isn't perfect ;) . And now when I'm trying to use it I got random SIGTRAP signals. If I comment out every line which are in connection with that memory manager everything runs fine. Getting SIGTRAP-s instead of SIGSEGV is quite strange.
I know that SIGTRAP-s are thrown when the program hits a breakpoint, but no breakpoint is set. I read in an other thread that debug builds of the exe's and dll's must be up to date. They are up to date and so it is not the reason.
Does anyone know why is this happening?
After searching on Google I realized that those sigtraps are same as those warnings you get in MSVC++ saying "Windows has triggered a breakpoint in xxxx.exe. This may be due to a corruption of the heap, and indicates a bug blahblahblah"...
So it seems yes, unexpected sigtraps can indicate memory corrupction (quite strange...)
And I found my bug too. The MM is in a static library which is linked to a dll. And that static lib and the dll is linked to my exe. So there were two memory managers, one in my exe and one in my dll. If call the initaialization method of the MM. It initialized the MM in my exe but not in the dll so the dll went without init. I solved this by not linking my exe against that static library.
I'd throw in a guess that you might be calling mismatched new/delete or malloc/free implementations - So something was allocated by your memory manager but when the memory is released you end up with the default delete/free implementation.
Set a breakpoint on the signal and see whether there is free() or operator delete on the stack and whether that is the implementation of said function which you would expect.
I am creating a C++ Win32 dll with some global data. There is a std::map defined globally and there are exported functions in the dll that write data into the map (after acquiring a write lock, ofcourse).
My problem is, when I call the write function from inside the dll DllMain, it works without any problems. But when I load the dll from another program and call the function that writes data into the global map, it gives me this error:
WindowsError: exception: access violation reading 0x00000008
Is there something that can be done about this? The same function when called from DllMain has access to the global data in the dll, but when called from a different process, it doesn't have access to the global data. Please advice.
I am using the TDM-MinGW gcc 4.4.0 Compiler.
EDIT:
Ok, I've figured out what the problem is, and thanks for the help guys, but the problem was not with a constructor issue or inability to have maps in global space, but an issue in the boost::python that I'm using. I had tested it, but since I was calling the dll from within python or maybe something, the urllib2 module wasn't getting loaded into the dll. Now I have to see how to fix it.
Looks like the constructor of std::map did not run yet when your code was called. Lifetime of global non-PODs in a Win32 DLL is pretty tricky, and I'm not certain as to how MinGW specifically handles it. But it may be that the way you're compiling the DLL, you've set your own function (DllMain?) as an entry point, and thus overrode the CRT initialization routine that calls constructors.
A read error at such a low memory address generally means that you are trying to access a NULL pointer somewhere. Can you show your actual code?
You have to use shared memory, because the different processes have separate address spaces.
I think you won't get std::map running. I would recommend using MapViewOfFile, CreateFileMapping, OpenFileMapping, ... and plain old data. Ask Google / MSDN.
I have to load modules as dlls dynamically at runtime as they are not known ahead of time, just that they conform to a class interface. What I noticed is that after I catch an exception thrown by the dll (in the main program in the main thread), the right destructors are called and the modules destroyed and dll's unloaded, but then as the } at the end of the catch block is reached by the Visual Studio C++ debugger when stepping line by line, I get another exception which crashes the program with
First-chance exception at 0x68ad2377 (msvcr90d.dll) in xxxxx.exe: 0xC0000005: Access violation reading location 0x02958f14.
If I enable breaking on exceptions, breaking on this second exception shows the location as
msvcr90d.dll!__DestructExceptionObject(EHExceptionRecord * pExcept=0x0017ee4c, unsigned char fThrowNotAllowed=0) Line 1803 + 0xf bytes
but it looks like the frame stack may be corrupt. I can't figure out why this exception is thrown.
A simplified version of my code structure is as follows:
A very simplified structure of the program:
//shared header:
class Module
{
public:
virtual void Foo(void) = 0;
};
//dll:
class SomeSpecificModule : public Module
{
public:
virtual void Foo(void);
};
void SomeSpecificModule::Foo(void)
{
throw 1;
}
extern "C" __declspec(dllexport) Module* GetModule()
{
return new SomeSpecificModule;
}
//program:
typedef ptrGetModule* (*GetModule)();
int main(void)
{
HANDLE hMod = LoadLibrary("SomeSpecificModule.dll");
ptrGetModule GetModule = (ptrGetModule)GetProcAddress(hMod, "GetModule");
try
{
Module *d = GetModule();
d->Foo();
}
catch (...)
{
cout << '!' << endl;
}
return 0;
}
The thing to remember is that each copy of C runtime library has its own states. If SomeSpecificModule.dll is linking statically to the C runtime library, this kind of problem may happen. If that's the case, try linking with DLL version of of C runtime library. You also have to make sure SomeSpecificModule.dll is compiled and linked exactly the same way as your main module.
You mentioned DLL being unloaded and correct destructors were called, it sounded like your real program has a lot more going on than the sample you posted. If you unloaded SomeSpecificModule.dll in your try block, you've unloaded the exception record for SomeSpecificModule::Foo(), and I guess that's how you got the crash at msvcr90d.dll!__DestructExceptionObject(EHExceptionRecord * ...
However, in general throwing exception across DLL boundaries is asking for trouble. If you're throwing non POD object, you may run into issue with memory allocated by different C runtime library in different heap, different compiler setting, STL version...you get the point.
Change you code so you don't throw across DLL boundaries. One day someone from your team change the compiler setting or a third party header #define changed and your program start crashing you're going to have a very hard time tracing down the root cause.
Anyway, without seeing the real code, I'm just trying to guess what might go wrong. Hope it helps.
Much of the stack unwinding code that needs to be called when your DLL throws an exception is in the DLL. If you unload the DLL, how is that code to be called?
Don't throw exceptions across dynamically linked module boundaries.
Are you cathing the exception by value in your actual code? In this case there may be an exception in the destructor of the copied exception object at the end of catch block.
I don't see in this code where the DLL is unloaded (as you say it is). Can you please post the relevant code?
The DLL's unloading may be crucial, since your DLL contains the code necessary for destructing objects, unwinding the stack, etc. and it isn't clear from what you posted at which point the DLL is unloaded.
Check poject settings, if your application is multithreaded then you should link to multithreaded DLL
Canopus: when I throw an int as the exception, the same thing happens.
TK___: I am linking to multithreaded dll in all projects.
Assaf and Shing Yip: The dll's are indeed unloaded by FreeLibrary() in the destructor of a wrapper for them, as the wrapper objects I push into a vector of tr1::shared_ptr (as the wrapper itself is noncopyable as a resource holder and so can't be put in an STL vector) existing only in the try{} scope. It seemed like the right thing to do, so I can make sure cleanup including DLL unloading when there is an error situation, and I tend to prefer RAII-style design. If this is the source of the problem, then I'm wondering what sort of design to use that would operate correctly and still look good from a software engineering perspective.
What makes me suspect this may not be the problem, however, is that when I step through the destructor calls that occur when the exception is thrown, FreeLibrary() runs with no error, and I can continue stepping until I get to the closing } of the catch{}.
Magnus Skog: In release mode I also get a crash rather than catching the exception then continuing execution normally.
Dynamic memory is handled with 1) operator new in a few cases, 2) tr1::shared_ptr, and 3) _mm_malloc/_mm_free where I need alignment.
This might be a shot in the dark, but worth checking out.
Your application seems to be compiled in DEBUG since the error shows up in msvcr90d.dll. Are the dlls you are using also compiled in DEBUG? Creating memory with msvcr90.dll and freeing with msvcr90d.dll or vice versa is a common problem when using dlls.
I think your function pointer typedef looks a little suspicious. I'd write it like this:
typedef Module* (*moduleFnType)();
int main(void)
{
HANDLE hMod = LoadLibrary("SomeSpecificModule.dll");
moduleFnType GetModule = (moduleFnType)GetProcAddress(hMod, "GetModule");
try
{
Module *d = GetModule();
d->Foo();
}
catch (...)
{
cout << '!' << endl;
}
return 0;
}
Your typedef doesn't say anything about the return type of the function GetModule.