Results 1 to 14 of 14

Thread: A wierd problem (ClanLib 2.3 SVN), GRR!

  1. #1
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Angry A wierd problem (ClanLib 2.3 SVN), GRR!

    ClanLib has a strange exception handler inside win32_window.cpp at line 433:
    Code:
    	__try
    	{
    		return static_window_proc(wnd, msg, wparam, lparam);
    	}
    	__except(cl_grr(exception_info()))
    	{
    		// A special thanks to whoever at Microsoft chose to eat access violations during WM_PAINT calls.
    		return DefWindowProc(wnd, msg, wparam, lparam);
    	}
    I can't understand what's the purpose of this code snippet. But it catches every exception (even CL_Exception), which occures inside main window message handler procedure.


    Real example:

    I'm using some GUI theme with the help of CL_GUIManager. The theme has (inside resource.xml):
    HTML Code:
    	<image name="SomeImage">
    		<image file="some_image.png" />
    	</image>
    and this image is used inside theme.css, but let's consider that the file some_image.png doesn't exist!

    What we get in this case:
    When I use a GUI component using this image, iodevice_provider_file.cpp throws an exception at line 68 of type CL_Exception. But this happens inside WM_PAINT window handler, so this exception is catched by the handler described above and the program crashes without any reason (we can't see and analyze the reason, cause we can't catch this CL_Exception)!


    I think there should be a way to fix this problem. What do developers think? What about using something like:
    Code:
    try
    {
      return static_window_proc(wnd, msg, wparam, lparam);
    }
    catch(const CL_Exception&)
    {
      throw;
    }
    catch(...)
    {
      return DefWindowProc(wnd, msg, wparam, lparam);
    }
    In fact, why do we need this handler?!
    Last edited by user; 11-26-2011 at 01:31 PM.

  2. #2
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    Ah, the famous cl_grr.

    The truth is that it was an accident that it got committed in its current form. But here's the problem it was trying to address:

    ClanLib is a C++ library using exceptions, but its running on top of Win32 which is a C API that doesn't use exceptions. What this means is that it is technically not correct to throw an exception and let it fall through Win32 API callback code, such as when we call DispatchMessage.

    If something throws an exception and nothing catches it, the exception rollback will eventually reach the Win32 window procedure and from there we HAVE to handle it. It cannot fall through any further since that is through Win32 C code where exceptions do not exist. So if an exception reaches the window procedure it should crash now in the same way as when the main function didn't catch an exception.

    Another detail is that the Win32 API does have structured exceptions, which is what that __try/__catch thing is trying to intercept. Access violations and other CPU exceptions are generated as structured exceptions. But those types of exceptions are not the same as C++ exceptions. The structured type is asynchronous (any instruction can generate it) while the C++ exceptions can only be generated by C++ code. This means that a normal C++ try/catch does not catch structured exceptions and it also does not throw structured exceptions. Therefore a C++ exception is not allowed fall through C callback code.

    Anyway, for some reason I had a problem with a program that would simply not crash on an access violation when the call happened in a WM_PAINT call. My debugging showed that something inside DispatchMessage caught the structured exception and ate it. The cl_grr code is there to try force a crash of the application NOW so you get a call stack with a debugger, and as you can see on that code it is really really trying to shut down that process in a debug-able way. And the sad thing is it fails at it, somehow prompting recursive cl_grr calls until it finally crashes with an useless stack trace.

    Some of the code uses a little trick where it creates an object with a destructor, and then it uses a bool variable to detect if the destructor is called normally or as a C++ exception rollback. It is doing it this way because if you catch an exception and then crash the application, then you do not get the call stack from where the exception was thrown. Not that this matters much when someone at Microsoft decided that WM_PAINT is not allowed to crash (yes, lets leave the application in an undetermined state instead.. great idea).

    If you have any good ideas on how to force a crash at the specific spot that WM_PAINT won't be able to magically catch and eat, then I'm all ears.

  3. #3
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Default

    Well, the problem is really difficult
    Actually, when the program has crashed after usual CL_Exception was thrown inside WM_PAINT, there was no readable callstack, so I spent some time debugging step-by-step... I was not able to see the actual location where the exception was thrown. As far as I know, C++ exceptions are based on structured exceptions, so about 40 top callstack entries were lost as the exception was caught by __catch inside win32_window.cpp.
    I spent about 30 minutes to get something like this:
    Code:
          SpriteEditor.exe!CL_IODeviceProvider_File::CL_IODeviceProvider_File(const CL_String8 & filename={...}, CL_File::OpenMode open_mode=open_existing, unsigned int access=1, unsigned int share=7, unsigned int flags=0)  Line 68     C++
          SpriteEditor.exe!CL_File::CL_File(const CL_String8 & filename={...}, CL_File::OpenMode open_mode=open_existing, unsigned int access=1, unsigned int share=7, unsigned int flags=0)  Line 81 + 0xa2 bytes     C++
          SpriteEditor.exe!CL_VirtualFileSource_File::open_file(const CL_String8 & filename={...}, CL_File::OpenMode mode=open_existing, unsigned int access=1, unsigned int share=7, unsigned int flags=0)  Line 70 + 0x43 bytes     C++
          SpriteEditor.exe!CL_VirtualFileSystem::open_file(const CL_String8 & filename_rel={...}, CL_File::OpenMode mode=open_existing, unsigned int access=1, unsigned int share=7, unsigned int flags=0)  Line 224 + 0x86 bytes     C++
          SpriteEditor.exe!CL_VirtualDirectory::open_file(const CL_String8 & filename={...}, CL_File::OpenMode mode=open_existing, unsigned int access=1, unsigned int share=7, unsigned int flags=0)  Line 143 + 0x56 bytes     C++
          SpriteEditor.exe!CL_PNGProvider_Impl::init()  Line 114 + 0x27 bytes     C++
          SpriteEditor.exe!CL_PNGProvider_Impl::CL_PNGProvider_Impl(const CL_String8 & name={...}, const CL_VirtualDirectory & directory={...})  Line 58     C++
          SpriteEditor.exe!CL_PNGProvider::load(const CL_String8 & filename={...}, const CL_VirtualDirectory & directory={...})  Line 74 + 0x13 bytes     C++
          SpriteEditor.exe!CL_ProviderType_Register<CL_PNGProvider>::load(const CL_String8 & filename={...}, const CL_VirtualDirectory & directory={...})  Line 64 + 0x11 bytes     C++
          SpriteEditor.exe!CL_ImageProviderFactory::load(const CL_String8 & filename={...}, const CL_VirtualDirectory & directory={...}, const CL_String8 & type={...})  Line 87 + 0x21 bytes     C++
          SpriteEditor.exe!CL_Texture::CL_Texture(CL_GraphicContext & context={...}, const CL_StringRef8 & filename={...}, const CL_VirtualDirectory & directory={...}, const CL_ImageImportDescription & import_desc={...})  Line 191 + 0x4c bytes     C++
          SpriteEditor.exe!CL_SharedGCData_Impl::load_texture(CL_GraphicContext & gc={...}, const CL_String8 & filename={...}, const CL_VirtualDirectory & virtual_directory={...}, const CL_ImageImportDescription & import_desc={...})  Line 76 + 0x31 bytes     C++
          SpriteEditor.exe!CL_SharedGCData::load_texture(CL_GraphicContext & gc={...}, const CL_String8 & filename={...}, const CL_VirtualDirectory & virtual_directory={...}, const CL_ImageImportDescription & import_desc={...})  Line 56 + 0x23 bytes     C++
          SpriteEditor.exe!CL_SpriteDescription::CL_SpriteDescription(CL_GraphicContext & gc={...}, const CL_StringRef8 & resource_id={...}, CL_ResourceManager * resources=0x033700fc, const CL_ImageImportDescription & import_desc={...})  Line 119 + 0x22 bytes     C++
          SpriteEditor.exe!CL_Image::CL_Image(CL_GraphicContext & gc={...}, const CL_StringRef8 & resource_id={...}, CL_ResourceManager * resources=0x033700fc, const CL_ImageImportDescription & import_desc={...})  Line 163 + 0x1b bytes     C++
          SpriteEditor.exe!CL_GUIThemeProvider_Default::get_image(CL_GraphicContext & gc={...}, CL_GUIComponent * component=0x03eac038, const CL_StringRef8 & name={...})  Line 523 + 0x58 bytes     C++
          SpriteEditor.exe!CL_GUIThemeProvider_Default::get_background_image(CL_GraphicContext & gc={...}, CL_GUIThemePart & part={...})  Line 156 + 0x2f bytes     C++
          SpriteEditor.exe!CL_GUIThemeProvider_Default::render_image_stretch_background(CL_GraphicContext & gc={...}, CL_GUIThemePart & part={...}, const CL_Rect & rect={...}, const CL_Rect & clip_rect={...})  Line 305 + 0x10 bytes     C++
          SpriteEditor.exe!CL_GUIThemeProvider_Default::render_image_background(CL_GraphicContext & gc={...}, CL_GUIThemePart & part={...}, const CL_Rect & rect={...}, const CL_Rect & clip_rect={...})  Line 151     C++
          SpriteEditor.exe!CL_GUIThemeProvider_Default::render_background(CL_GraphicContext & gc={...}, CL_GUIThemePart & part={...}, const CL_Rect & rect={...}, const CL_Rect & clip_rect={...})  Line 135     C++
          SpriteEditor.exe!CL_GUIThemeProvider_Default::render_box(CL_GraphicContext & gc={...}, CL_GUIThemePart & part={...}, const CL_Rect & rect={...}, const CL_Rect & clip_rect={...})  Line 116     C++
          SpriteEditor.exe!CL_GUITheme::render_box(CL_GraphicContext & gc={...}, CL_GUIThemePart & part={...}, const CL_Rect & rect={...}, const CL_Rect & clip_rect={...})  Line 114 + 0x2c bytes     C++
          SpriteEditor.exe!CL_GUIThemePart::render_box(CL_GraphicContext & gc={...}, const CL_Rect & rect={...}, const CL_Rect & clip_rect={...})  Line 289     C++
          SpriteEditor.exe!CL_GroupBox_Impl::on_render(CL_GraphicContext & gc={...}, const CL_Rect & update_rect={...})  Line 102     C++
          SpriteEditor.exe!CL_Callback_Impl_v2_member<CL_GraphicContext &,CL_Rect const &,CL_GroupBox_Impl>::invoke(CL_GraphicContext & p1={...}, const CL_Rect & p2={...})  Line 105 + 0x18 bytes     C++
          SpriteEditor.exe!CL_Callback_v2<CL_GraphicContext &,CL_Rect const &>::invoke(CL_GraphicContext & p1={...}, const CL_Rect & p2={...})  Line 230 + 0x22 bytes     C++
          SpriteEditor.exe!CL_GUIComponent::render(CL_GraphicContext & gc={...}, const CL_Rect & clip_rect={...}, bool include_children=true)  Line 736     C++
          SpriteEditor.exe!CL_GUIComponent::render(CL_GraphicContext & gc={...}, const CL_Rect & clip_rect={...}, bool include_children=true)  Line 763     C++
          SpriteEditor.exe!CL_GUIComponent::paint(const CL_Rect & clip_rect={...})  Line 788     C++
          SpriteEditor.exe!CL_GUIManager_Impl::on_paint(CL_GUITopLevelWindow * toplevel_window=0x033f9cc0, const CL_Rect & update_rect={...})  Line 670     C++
          SpriteEditor.exe!CL_Callback_Impl_v2_member<CL_GUITopLevelWindow *,CL_Rect const &,CL_GUIManager_Impl>::invoke(CL_GUITopLevelWindow * p1=0x033f9cc0, const CL_Rect & p2={...})  Line 105 + 0x18 bytes     C++
          SpriteEditor.exe!CL_Callback_v2<CL_GUITopLevelWindow *,CL_Rect const &>::invoke(CL_GUITopLevelWindow * p1=0x033f9cc0, const CL_Rect & p2={...})  Line 230 + 0x22 bytes     C++
          SpriteEditor.exe!CL_GUIWindowManagerProvider_System::on_displaywindow_paint(const CL_Rect & rect={...}, CL_GUITopLevelWindow * top_level_window=0x033f9cc0)  Line 92     C++
          SpriteEditor.exe!CL_SlotCallback_v1_member_user<CL_Rect const &,CL_GUIWindowManagerProvider_System,CL_GUITopLevelWindow *>::invoke(const CL_Rect & param1={...})  Line 92 + 0x2a bytes     C++
          SpriteEditor.exe!CL_Signal_v1<CL_Rect const &>::invoke(const CL_Rect & param1={...})  Line 188 + 0x29 bytes     C++
          SpriteEditor.exe!CL_Win32Window::window_proc(HWND__ * wnd=0x002610d4, unsigned int msg=15, unsigned int wparam=0, long lparam=0)  Line 781     C++
         SpriteEditor.exe!CL_Win32Window::static_window_proc(HWND__ * wnd=0x002610d4, unsigned int msg=15, unsigned int wparam=0, long lparam=0)  Line 577 + 0x18 bytes     C++
          SpriteEditor.exe!CL_Win32Window::static_window_try_proc(HWND__ * wnd=0x002610d4, unsigned int msg=15, unsigned int wparam=0, long lparam=0)  Line 435 + 0x15 bytes     C++
          user32.dll!754e8817()      
          [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]     
          user32.dll!754e898e()      
          user32.dll!754e8921()      
          user32.dll!754ec47c()      
          user32.dll!754ec4a2()      
          opengl32.dll!5ae3834f()      
          user32.dll!754e8817()      
          user32.dll!754e898e()      
          user32.dll!754e8921()      
          user32.dll!754e9d14()      
          user32.dll!754e9d85()      
          ntdll.dll!7747e496()      
          ntdll.dll!7747e496()      
          user32.dll!754ec12b()      
          user32.dll!754e8b10()      
          SpriteEditor.exe!CL_DisplayMessageQueue_Win32::process_message()  Line 213 + 0xc bytes     C++
          SpriteEditor.exe!CL_DisplayMessageQueue_Win32::wait(const std::vector<CL_Event,std::allocator<CL_Event> > & events=[0](), int timeout=0)  Line 82     C++
          SpriteEditor.exe!CL_Callback_Impl_2_member<int,std::vector<CL_Event,std::allocator<CL_Event> > const &,int,CL_DisplayMessageQueue_Win32>::invoke(const std::vector<CL_Event,std::allocator<CL_Event> > & p1=[0](), int p2=0)  Line 105 + 0x18 bytes     C++
          SpriteEditor.exe!CL_Callback_2<int,std::vector<CL_Event,std::allocator<CL_Event> > const &,int>::invoke(const std::vector<CL_Event,std::allocator<CL_Event> > & p1=[0](), int p2=0)  Line 230 + 0x22 bytes     C++
          SpriteEditor.exe!CL_KeepAlive::process(int timeout=0)  Line 76 + 0x12 bytes     C++
          SpriteEditor.exe!CL_GUIManager::process_messages(int timeout=-1)  Line 269 + 0x9 bytes     C++
          SpriteEditor.exe!CL_GUIManager::exec()  Line 296     C++
          SpriteEditor.exe!sprite_editor::start()  Line 182 + 0xb bytes     C++
          SpriteEditor.exe!Program::main(const std::vector<CL_String8,std::allocator<CL_String8> > & args=[1]({data_capacity=88 local_string=0x00d91c34 "" }))  Line 68 + 0x2c bytes     C++
          SpriteEditor.exe!WinMain(HINSTANCE__ * hInstance=0x00f40000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00634f23, int nCmdShow=1)  Line 87 + 0xc bytes     C++
          SpriteEditor.exe!__tmainCRTStartup()  Line 275 + 0x2c bytes     C
          SpriteEditor.exe!WinMainCRTStartup()  Line 189     C
          kernel32.dll!7507f13c()      
          ntdll.dll!774dd80d()      
          ntdll.dll!774dda1f()
    Well, I'll think about this problem some more time, maybe there're better ways to handle it.

  4. #4
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    After looking at bit more at the /EH compiler options, it does seem like C++ exceptions are always implemented in Visual C++ as structured exceptions. It is just that per default it no longer safely destroys C++ objects if it gets a structured exception originating from somewhere else than C++ throw statements (or extern C functions).

    But by the end of the day this still doesn't solve my original problem, which was that something inside Win32 catches and eats all exceptions thrown in a WM_PAINT call. If you remove/disable the cl_grr related code, you won't get a crash with your call stack. What you will get is a white screen instead since the render code throws an exception and Win32 catches and silences it.

  5. #5
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    OK, managed to fix this problem with the help of huntercool's search skills.

    It turns out that the problem is known and a workaround exists: http://support.microsoft.com/kb/976038

    You don't have to actually apply this hotfix. At least my Windows 7 already had these functions in kernel32.dll and after calling them the problem seem to be solved. Either way, if ClanLib finds the functions it enables the workaround, otherwise the access violations and exceptions will be silently eaten. The patch has been committed to both 2.3 and 2.4 SVN.

    So no more cl_grr in ClanLib.

  6. #6
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Default

    Quote Originally Posted by Magnus Norddahl View Post
    OK, managed to fix this problem with the help of huntercool's search skills.

    It turns out that the problem is known and a workaround exists: http://support.microsoft.com/kb/976038

    You don't have to actually apply this hotfix. At least my Windows 7 already had these functions in kernel32.dll and after calling them the problem seem to be solved. Either way, if ClanLib finds the functions it enables the workaround, otherwise the access violations and exceptions will be silently eaten. The patch has been committed to both 2.3 and 2.4 SVN.

    So no more cl_grr in ClanLib.
    Well, this solution is not working on my Vista x64 (Because I haven't installed that patch, so I get just an empty window if any exceptions occured inside WM_PAINT). There's also a small problem during compilation now: win32_window lines 486 and 365 - CL_ExceptionCatcher is undefined. Somebody should remove these lines from SVN sources...
    Last edited by user; 11-27-2011 at 10:51 AM.

  7. #7
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Default

    I could realize only the unnatural way of solving the problem without using any patches, something like this:
    PHP Code:
    #include <Windows.h>
    #include <exception>
    #include <iostream>
    #include <fstream>
    #include <map>
    #include <conio.h>
    //Using Dialog boxes just for example
    #include "resource.h"

    //Helper structure
    struct cpp_exception
    {
        
    cpp_exception()
            :empty(
    true)
        {}

        
    std::exception e;

        
    //if "e" is empty
        
    bool empty;
    };

    //static exception map for all existing application windows
    static std::map<unsigned longcpp_exceptioncpp_wndproc_exception_list;
    //Helper exception message
    static const unsigned long WM_CPP_EXCEPTION WM_USER 1;

    //Counter of existing windows
    static unsigned long window_count 0;

    //Main Dialog message procedure
    INT_PTR CALLBACK DlgProcFunc(HWND hWndDlgUINT MsgWPARAM wParamLPARAM lParam)
    {
        
    //Usual C++ exception handler
        
    try
        {
            switch(
    Msg)
            {
            case 
    WM_INITDIALOG:
                
    //Set up exception handling for current window
                
    cpp_wndproc_exception_list.insert(std::make_pair(reinterpret_cast<unsigned long>(hWndDlg), cpp_exception()));
                break;

            case 
    WM_PAINT:
                
    //Throwing std::exception from WM_PAINT
                
    throw std::exception("Test!");
                break;

            case 
    WM_CLOSE:
                
    cpp_wndproc_exception_list.erase(reinterpret_cast<unsigned long>(hWndDlg));

                
    window_count--;
                if(!
    window_count)
                    
    PostQuitMessage(0);

                
    DestroyWindow(hWndDlg);
                break;
            }
        }
        catch(const 
    std::exceptione)
        {
            
    //C++ excepion handler
            
    cpp_exceptionex_info cpp_wndproc_exception_list.at(reinterpret_cast<unsigned long>(hWndDlg));
            
    ex_info.e;
            
    ex_info.empty = false;
            
    //Sending helper exception message to main exception loop
            
    PostMessage(hWndDlgWM_CPP_EXCEPTION00);
        }

        return 
    0;
    }

    //Helper function to create new dialog-based window and set up exceptions for it
    HWND CreateAnotherWindow()
    {
        
    window_count++;
        
    HWND win CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), 0DlgProcFunc);
        
    ShowWindow(winSW_SHOWNORMAL);
        return 
    win;
    }

    int CALLBACK WinMain(
        
    __in  HINSTANCE hInstance,
        
    __in  HINSTANCE hPrevInstance,
        
    __in  LPSTR lpCmdLine,
        
    __in  int nCmdShow
        
    )
    {
        
    //Create some windows
        
    HWND win1 CreateAnotherWindow();
        
    HWND win2 CreateAnotherWindow();
        
    HWND win3 CreateAnotherWindow();

        try
        {
            
    //Main message loop
            
    MSG msg;
            while(
    GetMessage(&msgNULL00))
            {
                
    //If we get an exception from some window
                
    if(msg.message == WM_CPP_EXCEPTION)
                {
                    
    cpp_exceptionex_info cpp_wndproc_exception_list.at(reinterpret_cast<unsigned long>(msg.hwnd));
                    if(!
    ex_info.empty)
                    {
                        
    //Rethrow it
                        
    ex_info.empty = true;
                        throw 
    ex_info.e;
                    }
                }

                
    TranslateMessage(&msg);
                
    DispatchMessage(&msg);
            }
        }
        catch(const 
    std::exceptione)
        {
            
    //Actual exception handler

            
    cpp_wndproc_exception_list.clear();

            
    AllocConsole();

            
    // redirect std::cout to our console window
            
    std::streambufm_old_cout std::cout.rdbuf();
            
    std::ofstream m_out;
            
    m_out.open("CONOUT$");
            
    std::cout.rdbuf(m_out.rdbuf());

            
    //Print exception info
            
    std::cout << "A C++ exception transferred from WM_PAINT: " << e.what() << std::endl;
            while (!
    _kbhit()) Sleep(250);
        }

    Doesn't look good, but seems working...

  8. #8
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Maybe I am missing something... but I would have thought this following method would have been the simplest:


    Code:
    CL_Win32Window::window_proc()
    {
      if (exception_was_thrown)
      {
        this->panic = true;
        this->panic_exection = exception
      }
    }
    
    
    CL_DisplayMessageQueue_Win32::process_message()
    {
      if (window->panic)
      {
        throw window->panic_exception
      }
    }

  9. #9
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Default

    Quote Originally Posted by rombust View Post
    Maybe I am missing something... but I would have thought this following method would have been the simplest:[/CODE]
    I think, that's quite the same thing I suggested. But I'm not very good in ClanLib win32 windowing object model, so I included the full source code of my own example.

  10. #10
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    Are you using the latest service pack of Windows Vista? If not, try apply it - maybe the hotfix is included in it.

    Catching the exception and then re-throwing it from the DispatchMessage parent function would work for some scenarios. However it has several problems:
    1. Exception inheritance won't work. I know that ClanLib in general is really lazy about it and virtually only throw CL_Exception everywhere, but if someone was to throw a derived class, i.e. lets say a CL_XMLParseException class, then we can't catch and re-throw it as CL_XMLParseException. (Without a special catch clause for every derived type we know, that is)
    2. An unhandled exception would make the debugger point at the new throw location, not where the exception was originally thrown.
    3. Such a catch clause will not detect access violations and other similar bugs. So in those cases you'd still get the white screen effect.

    Stack overflow lists an alternative solution where the program attempts to remove all registered exception handlers. This solution is extremely hacky and will get rid of all catch clauses earlier in the program, but it would allow the application to at least crash. I don't think its a good idea to use this method unless there's no service pack for Vista that implements the official Microsoft hotfix.

  11. #11
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Default

    Quote Originally Posted by Magnus Norddahl View Post
    Are you using the latest service pack of Windows Vista? If not, try apply it - maybe the hotfix is included in it.
    Yes, I have the latest Service Pack with latest updates.

    Quote Originally Posted by Magnus Norddahl View Post
    Catching the exception and then re-throwing it from the DispatchMessage parent function would work for some scenarios. However it has several problems:
    1. Exception inheritance won't work. I know that ClanLib in general is really lazy about it and virtually only throw CL_Exception everywhere, but if someone was to throw a derived class, i.e. lets say a CL_XMLParseException class, then we can't catch and re-throw it as CL_XMLParseException. (Without a special catch clause for every derived type we know, that is)
    2. An unhandled exception would make the debugger point at the new throw location, not where the exception was originally thrown.
    3. Such a catch clause will not detect access violations and other similar bugs. So in those cases you'd still get the white screen effect.

    Stack overflow lists an alternative solution where the program attempts to remove all registered exception handlers. This solution is extremely hacky and will get rid of all catch clauses earlier in the program, but it would allow the application to at least crash. I don't think its a good idea to use this method unless there's no service pack for Vista that implements the official Microsoft hotfix.
    I've just tried the way rombust suggested (I re-throwed only CL_Exception and std::exception objects from WM_PAINT), and I think that this thing is better than using a patch included only in Windows 7 by default... At least, I can have a fair callstack and descriptive exception text.

    As for problem #1, if somebody throws CL_XMLParseException from WM_PAINT, it can be later caught as std::exception, and that's not bad, because you still have a callstack and exception message.

    I can upload a patch using this method, so you can try it yourself.

    And please somebody fix the SVN sources problem described in post #6

  12. #12
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    I have looked more at the problem, and learnt lot of things on the way

    Here clanlib crashed in CL_System::capture_stack_trace() when an exception was thrown during DispatchMessage()

    I created a patch to "fix it", except it was not broken, it was my silly error. My "fix" caused other developers to not be able to debug their code.

    For reference - This was my problem:

    The code crashed like this. I needed to load the KernelBase symbols by right clicking on it as follows:



    Then the code can be debugged:



    The symbols are cached for future use, so you only have to do this once

    (Attached is my broken patch)
    Attached Files Attached Files

  13. #13
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    I've committed a patch that applies the SEH workaround in the stackoverflow link if it can't find the official hotfix on the system.

    But you really just need to accept your fate, User. As a Vista user you're SUPPOSED to have the Vista Experience. But for now you can escape it just a little longer.

  14. #14
    Lesser Knight
    Join Date
    Jan 2011
    Posts
    32

    Default

    Quote Originally Posted by Magnus Norddahl View Post
    I've committed a patch that applies the SEH workaround in the stackoverflow link if it can't find the official hotfix on the system.

    But you really just need to accept your fate, User. As a Vista user you're SUPPOSED to have the Vista Experience. But for now you can escape it just a little longer.
    Thanks, I tried it and it worked for me (I needed to load kernel symbols, like rombust described).

    As for Vista, I have muuuuch experience with it, but I'm too lazy to back-up all my data and set up Win7

Similar Threads

  1. Clanlib (install) problem: mt-uc
    By astrof in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 12-11-2008, 10:32 PM
  2. Problem compiling ClanLib 0.8 in MAC OS X (10.3.9)
    By jplaza in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 07-08-2008, 09:58 PM
  3. Wierd Coloration in *some* demos
    By adam in forum Official ClanLib SDK Forums
    Replies: 4
    Last Post: 07-30-2007, 10:05 PM
  4. Wierd bug in old graphics card...
    By whisperstorm in forum Novashell Game Creation System
    Replies: 2
    Last Post: 05-08-2007, 12:34 AM
  5. Problem building ClanLib
    By jtaylor1126 in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 03-31-2007, 12:10 AM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •