[PATCH 2/7] msvcrt: Clean up registered C++ object in handler.

Daniel Lehman dlehman at esri.com
Tue May 30 17:59:14 CDT 2017


On 05/24/17 02:55, Daniel Lehman wrote:
> +static DWORD cxx_catch_cleanup(EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
> +                               CONTEXT *context, 
> +EXCEPTION_REGISTRATION_RECORD **pdispatcher) {
> +    if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
> +    {
> +        thread_data_t *data = msvcrt_get_thread_data();
> +        frame_info *cur;
> +
> +        if (cxx_is_consolidate(rec))
> Is this condition really needed? Shouldn't we clean the object no matter what's the reason of unwind?

Yeah.  That's covered by patch 7/7.  The original code only cleaned up if consolidating.  

Since this 2/7 patch was somewhat of a refactoring for the later patches, I kept the consolidate-only cleanup logic.  I can merge them if you want

>> +                if ((ULONG64)cur <= (ULONG64)frame)
> This condition is not working. It's making assumption about order of catch_frame and frame_info variables on stack while they are declared this way:

I see what you mean.  If I forcefully reverse them, my tests crash;  my version of gcc was always putting them in the same place on the stack, regardless of where they were declared

>> +    EXCEPTION_REGISTRATION_RECORD catch_frame;
>>       cxx_frame_info frame_info;
> Shouldn't the cxx_catch_cleanup just unregister the object that was registered in call_catch_block?

I didn't find a way to be call __CxxUnregisterObject on that one specifically (I'll try suggestions if you got em)

but the loop in cxx_catch_cleanup effective does this.  when unwinding a nested exception, cxx_catch_cleanup will be called when unwinding call_catch_block, so all objects registered in call_catch_block and below will be cleaned up at that point.  Unless the catch block itself explicitly calls __CxxRegisterObject, the only object on the list up to that frame will be the one from call_catch_block

> Here's a test case that demonstrate the problem with cur <= frame
> comparison:
>
>	try {
>		try { int *p = NULL; *p = 0x42; }
>		catch (klass x) { throw 1; }
>	} catch (int i) { }
>
>	try { throw 1; }
>	catch(...) {}

This crashes for me even on Windows because the SEGV is uncaught.  It 'works' if I set an seh translator that throws int, but I get identical results on Wine with my series applied.  Do I need to add something?

Thanks
daniel




More information about the wine-devel mailing list