none
SEH Exceptions. What SEH exceptions are processed by default with EXCEPTION_CONTINUE_EXECUTION?

    السؤال

  • Where can I find information how SEH exceptions are processing by default? There is no such info in MSDN. But I need this information to know what exceptions I must ignore and pass them to system with EXCEPTION_CONTINUE_SEARCH. I mean what SEH exceptions are processed by default with EXCEPTION_CONTINUE_EXECUTION and that's why my application don't terminated and continue execution? That's why I must not processing them with EXCEPTION_EXECUTE_HANDLER in the __except filter.

    These are all from WinBase.h:

    #define EXCEPTION_ACCESS_VIOLATION     STATUS_ACCESS_VIOLATION
    #define EXCEPTION_DATATYPE_MISALIGNMENT   STATUS_DATATYPE_MISALIGNMENT
    #define EXCEPTION_BREAKPOINT        STATUS_BREAKPOINT
    #define EXCEPTION_SINGLE_STEP        STATUS_SINGLE_STEP
    #define EXCEPTION_ARRAY_BOUNDS_EXCEEDED   STATUS_ARRAY_BOUNDS_EXCEEDED
    #define EXCEPTION_FLT_DENORMAL_OPERAND   STATUS_FLOAT_DENORMAL_OPERAND
    #define EXCEPTION_FLT_DIVIDE_BY_ZERO    STATUS_FLOAT_DIVIDE_BY_ZERO
    #define EXCEPTION_FLT_INEXACT_RESULT    STATUS_FLOAT_INEXACT_RESULT
    #define EXCEPTION_FLT_INVALID_OPERATION   STATUS_FLOAT_INVALID_OPERATION
    #define EXCEPTION_FLT_OVERFLOW       STATUS_FLOAT_OVERFLOW
    #define EXCEPTION_FLT_STACK_CHECK      STATUS_FLOAT_STACK_CHECK
    #define EXCEPTION_FLT_UNDERFLOW       STATUS_FLOAT_UNDERFLOW
    #define EXCEPTION_INT_DIVIDE_BY_ZERO    STATUS_INTEGER_DIVIDE_BY_ZERO
    #define EXCEPTION_INT_OVERFLOW       STATUS_INTEGER_OVERFLOW
    #define EXCEPTION_PRIV_INSTRUCTION     STATUS_PRIVILEGED_INSTRUCTION
    #define EXCEPTION_IN_PAGE_ERROR       STATUS_IN_PAGE_ERROR
    #define EXCEPTION_ILLEGAL_INSTRUCTION    STATUS_ILLEGAL_INSTRUCTION
    #define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION
    #define EXCEPTION_STACK_OVERFLOW      STATUS_STACK_OVERFLOW
    #define EXCEPTION_INVALID_DISPOSITION    STATUS_INVALID_DISPOSITION
    #define EXCEPTION_GUARD_PAGE        STATUS_GUARD_PAGE_VIOLATION
    #define EXCEPTION_INVALID_HANDLE      STATUS_INVALID_HANDLE
    #define EXCEPTION_POSSIBLE_DEADLOCK     STATUS_POSSIBLE_DEADLOCK

     

    • تم التحرير بواسطة Vladimir Belov 07/جمادى الأولى/1432 09:06 م
    07/جمادى الأولى/1432 08:02 م

جميع الردود

  • The simple rule is handle only what you need to. You can inadvertantly get in the way of a lot of things by handling all exceptions.

    Your better bet is to ignore exceptions by default but only handle a certain list, and it is the way all samples show you how to do it. That is

    __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
    

    you can see GetExceptionCode for a list of common exception errors, but this is not complete. Whats more it is possible to raise your own exceptions with their own codes by using the RaiseException function.


    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://ccprogramming.wordpress.com/
    07/جمادى الأولى/1432 08:39 م
  • All what you said I know, Crescens2k. But you didn't answer to my main question: What SEH exceptions are processed by default(by the Windows) with EXCEPTION_CONTINUE_EXECUTION and that's why my application don't terminated and continue execution? That's why I must not processing them with EXCEPTION_EXECUTE_HANDLER in the __except filter.


    It may be EXCEPTION_GUARD_PAGE or EXCEPTION_DATATYPE_MISALIGNMENT(for Itanium). I don't know and MSDN also don't say about this.


    07/جمادى الأولى/1432 08:55 م
  • Well one of the main points to make is that you really WANT your program to crash in most cases when an SEH is generated.  It means that something bad happened and any data and state you have is suspect and may be corrupt and you have no good way to tell what is good and what is bad.

    There may be limited times when you know that a certain block of code may generate an SEH and you can continue safely, in those cases do what Cresens2k suggested.  But frankly those times are pretty rare.

    If you do start trying to catch all exceptions that would crash you and try to continue from them you will likely find yourself in "impossible" situations where perhaps an hour later your program does something horrible that doesn't make any sense.  Those are incredibly nasty to debug and I would suggest that crashing is prefereable.

    Better yet, figure out what is triggering the SEH and fix it.

    08/جمادى الأولى/1432 07:32 ص
  • I am not sure what you mean.

    Any SE that reaches your code is absolutely not handled by the system. When that happens, you

    • either have a massive bug that you need to fix
    • either you are doing something +/- special and you know that you need to handle it.

    There is only one occasion I know where system would throw an exception that calling code needed to handle, and that was EnterCriticalSection under win2000, and even that was avoidable. There might be more, but I haven't seen that.

    Can you tell us what is the problem you are trying to solve?

    08/جمادى الأولى/1432 08:32 ص
  • Maybe you can create an experimental program that generates various system exceptions with RaiseException and see which ones do not terminate application (outside of Visual Studio), if any?

    08/جمادى الأولى/1432 01:33 م
  • Maybe you can create an experimental program that generates various system exceptions with RaiseException and see which ones do not terminate application (outside of Visual Studio), if any?

     

    Interesting suggestion, but how can we reproduce  that error because of which there should be an exception? Otherwise the system can't correctly perform the operation on elimination of this error. I know how to reproduce some errors without RaiseException, but not all of them.

    08/جمادى الأولى/1432 06:43 م
  • Any SE that reaches your code is absolutely not handled by the system. When that happens, you

    If it is so absolutely -- I am happy :).  It is exactly what I need. But, Goran, what about EXCEPTION_DATATYPE_MISALIGNMENT(for Itanium) for example. Is it also  absolutely not handled by the system and the system can't fix it?

    Can you tell us what is the problem you are trying to solve?

     I want total control for exceptions in my code. At least to write down in a log-file these events. That is for my own code. And I can proceed all exceptions with EXCEPTION_CONTINUE_SEARCH in filter, give their to the system to handling. I only will have writing the log, that is enough. That is for my own code.

    But for third-party code(DLLS) I want to catch SEH exceptions so much as possible. But if there are exceptions that don't lead to shutting down the program I must know their, to let the system to proceed them with EXCEPTION_CONTINUE_SEARCH in filter and so let the third-party function(program) to continue the work.



    08/جمادى الأولى/1432 06:58 م
  • Any SE that reaches your code is absolutely not handled by the system. When that happens, you

    If it is so absolutely -- I am happy :).  It is exactly what I need. But, Goran, what about EXCEPTION_DATATYPE_MISALIGNMENT(for Itanium) for example. Is it also  absolutely not handled by the system and the system can't fix it?

    Can you tell us what is the problem you are trying to solve?

     I want total control for exceptions in my code. At least to write down in a log-file these events. That is for my own code. And I can proceed all exceptions with EXCEPTION_CONTINUE_SEARCH in filter, give their to the system to handling. I only will have writing the log, that is enough. That is for my own code.

    But for third-party code(DLLS) I want to catch SEH exceptions so much as possible. But if there are exceptions that don't lead to shutting down the program I must know their, to let the system to proceed them with EXCEPTION_CONTINUE_SEARCH in filter and so let the third-party function(program) to continue the work.




    I don't know much about Itanium, but I do have a first idea about the need to align your data properly depending on hardware architecture. This certainly falls under "it's a bug in code, must fix it" category. I know that you can come into this situation from e.g. casting, in C++, that was due to reinterpret_cast (or blind C cast that amounted to same), and that is platform-specific, and if platform doesn't allow it, well, tough, must be fixed.

    About the "total control over exceptions"... I am pretty certain that, in majority of situations, attempts to log and continue upon a bug (which is what SE normally indicates) are a bad idea. I would suggest that you simply crash and either use Windows Error Reporting, either create a crash dump of your own and analyze that. You seem to have the notion that logging an SE will help you, and I think that this notion is false.

    If you have third-party code that emits SEs... SEs are pretty drastic and if that code does use them for legitimate reasons, it must be pretty well documented. If not, if code has bugs, I would suggest that you either press the vendor to fix, fix it yourself if possible, or find a workaround.

    At any rate, a decision to continue after a bug has been detected is seldom wise. If you still want to continue running, I would suggest that you build external resiliency features (e.g. a monitoring program that restarts your program upon a crash).

    Goran.

    • تم وضع علامة كإجابة بواسطة lucy-liuModerator 07/جمادى الثانية/1432 09:57 ص
    • تم إلغاء علامة كإجابة بواسطة lucy-liuModerator 07/جمادى الثانية/1432 09:57 ص
    09/جمادى الأولى/1432 08:40 ص
  • I want to emphasize what Goran said.  You don't want to continue after an exception.  If you are lucky you will just crash again right away.  If you are unlucky you will corrupt the value of some variable in your program which will cause it to behave in ways that are impossible to track and debug.
    • تم الاقتراح كإجابة بواسطة lucy-liuModerator 07/جمادى الثانية/1432 09:57 ص
    09/جمادى الأولى/1432 01:23 م
  • Goran:

    There is one exception which is thrown on x86/x64 which can be handled by the system on a somewhat regular basis, that is the guard page exception. Don't forget that the stack is growable and is protected by a guard page. That is the reason why certain Win32 API functions can cause a crash in such weird ways.


    Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.
    Visit my (not very good) blog at
    http://ccprogramming.wordpress.com/
    09/جمادى الأولى/1432 06:04 م
  • Goran:

    There is one exception which is thrown on x86/x64 which can be handled by the system on a somewhat regular basis, that is the guard page exception. Don't forget that the stack is growable and is protected by a guard page. That is the reason why certain Win32 API functions can cause a crash in such weird ways.




    Well, that is IMO exactly the case where application interacts with the system in a particular way, and application knows it must handle such exceptions.

    Or am I missing something? What crashes do you have in mind, BTW?

    Goran.


    10/جمادى الأولى/1432 10:40 ص
  • Just ran across this old thread. Kinda interesting. Depends on what you call 'handling' .  There is a default SEH exception handler plugged into the startup code of most compilers. If you are doing an app in asm, it then goes all the way back to the system default handler. It and/or they are installed in a chain list at FS:0 location. The above said handlers merely save the crash and give an exit with msg. Neither one of these actually handle the exception from the point of view that you are saying when you pass EXCEPTION_CONTINUE_EXECUTION.  When you pass continue you are telling the exception framework that you have corrected the context of the offending eip address params and it is (now) ok to continue. If you have not done this, it's simply going to raise another exception and return to the filter again over and over until the stack finally gets so corrupted the app will crash.  If I'm handling an exception in an SEH _try _except block, I do it inside the (my) filter function which is called in the _except filter expression.  I do not attempt to handle the exception unless I am sure it is MY known point of exception and it is in fact the type of exception I am prepared to handle. I test this by comparing the exception addr passed from the context struck to the previously recorded eip addr that could have had an exception. I get this pre-recorded test addr like this,

    _asm
    {    
      mov ecx, this              //using C++ Class scope vars so requires 'this' + offset in asm
      mov eax, TEST_EIP          //Grab the (possible) offending addr for later verification
      mov [ecx + OurEaddr], eax
      mov ebx, [ecx + ppScratch]
    TEST_EIP:   mov eax, [ebx]   // test for violation, will except to filter if so.
    } // end asm   // if you get here the param is safe for further use.

    // then in my filter func I have the following
    DWORD MyViolationFilter( unsigned int E_code, struct _EXCEPTION_POINTERS *pE )
    {         
     void* E_addr = pE->ExceptionRecord->ExceptionAddress;
     DWORD E_flag = pE->ExceptionRecord->ExceptionFlags;
     if (E_code == STATUS_ACCESS_VIOLATION && pMyFileClass->OurEaddr == (DWORD)E_addr) 
     {
      pMyFileClass->E_Occur = 1;   // Set this to notify returning process that except has occured.
      pE->ContextRecord->Ebx = (DWORD)pMyFileClass->ppSafe;  // restore context to safe value
      return EXCEPTION_CONTINUE_EXECUTION;  // continues at faulting addr,
     }           
     else   // definitely not our access violation, pass it on.
     {    
      return EXCEPTION_CONTINUE_SEARCH;
     }
    } // end my filter handler

    The thing to keep in mind is if you don't know exactly what you are handling and how to handle it you should pass EXCEPTION_CONTINUE_SEARCH.  AND ANOTHER THING is WHAT you are defining as HANDLING the exception. The above handles it ONLY in the facet that it corrects the offense and allows the program to continue without a corrupted stack (which is what would happen if you just jmp'd out of the handler to the addr just after the offense without corrected the context and allowing the framework to follow it's own code back. But even so the above does not address things like should you close files or delete pts etc. This all has to be taken in to account to trully handle an exception. I ONLY USE THE ABOVE CODE FOR DEBUGGING PURPOSES. It is somewhat futile to handle access violations in a release build other than to report the issue so it might be corrected in an update.

    To answer you original question, NONE of your exceptions are handled by the system other than to notify (and possibly exit with a msg) you that an exception in your code just happened.  You are the only one that can handle them in a way that you can safetly pass continue on them. If not then pass keep searching.

     


    JW
    09/رمضان/1432 12:05 ص
  • You are not at the level low enough to catch all exceptions. Consider that the OS has the first chance to see the exception, for example, a page fault. Then it can either handle it internally or translate to some SEH exception and pass back to usermode to sort out. Internals of Windows are (of course) undocumented, this is why you cannot find the documentation. (This is even more encumbered by virtualization, as some instructions may be catched by a hypervisor, etc.)

    Regards,

    --pa

    09/رمضان/1432 03:15 ص
  • You are not at the level low enough to catch all exceptions. Consider that the OS has the first chance to see the exception, for example, a page fault. Then it can either handle it internally or translate to some SEH exception and pass back to usermode to sort out. Internals of Windows are (of course) undocumented, this is why you cannot find the documentation. (This is even more encumbered by virtualization, as some instructions may be catched by a hypervisor, etc.)

    Regards,

    --pa


    Well this is correct, most OS's do in fact implement guard page checking and handling (expansion of growth and allocation needs). But I view this as part of the OS's own memory management and allocation code. Granted it is an exception and is being handled by the OS, so you are correct, but I don't really view it as an exception from the user code but rather an exception within the OS processes. That's just my opinion.  But admittedly the user code can cause this exception.

    To be complete if ANY handler handles an exception as a continuable exception it should correct the problem so execution can continue and at least notify the user.  Page guards and access violations are 2 exceptions that can be continued after some tidying up (if you are specifically aware of what needs corrected). However most other exceptions cannot be handled so easily and if not handled by the user code, the defualt handler first will return an UNWINDING, which is passed back up thru the entire exception linked chain of handlers. Upon recieving this UNWINDING, any handler along the chain that has previously passed CONTINUE SEARCH can now call Dtors, close files etc, if they have not already chosen to do so. After all said handlers return back a second time, comes the final curtain from the default handler.

    The above applies to a custom handler you have written and installed in the FS:0 chain yourself.  As far as the _try/_except blocks, it's been awhile since I checked the logistics of it but I know the filter function (if you write one instead of just using an expression) will receive the first call on the exception (when the flag is 0) but the second callback, if I remember correctly, goes to the _except frame and skips the filter.  I do all my SEH handling in the filter function (where I can access the context etc) so none of my code ever makes it to the _except block, unless it's an exception I am not handling.

    This is all good stuff to learn especially for debugging. For runtime exceptions I would advocate using C++ try catch instead of the SEH _try/_except, for unwinding out of more user implemented exception issues that come up.  You could install a base SEH handler to report back data in case of non C++ asycronous exception, and some do. But it carries a performance hit. Hopefully all the SEH exceptions can be ironed out during development and you can just concentrate on sycronous C++ exceptions during runtime. Also keep in mind most newer compilers will not even compile for SEH excepton unless you tell them to with the appropriate switch.


    JW
    09/رمضان/1432 11:24 ص