Commit 46f29944 authored by Jukka Heinonen's avatar Jukka Heinonen Committed by Alexandre Julliard

Remove races from DPMI async event handling.

parent 9b4b21b7
......@@ -779,12 +779,6 @@ DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context )
case 0xfb: /* sti */
NtCurrentTeb()->dpmi_vif = 1;
context->Eip += prefixlen + 1;
if (NtCurrentTeb()->vm86_pending)
{
NtCurrentTeb()->vm86_pending = 0;
rec->ExceptionCode = EXCEPTION_VM86_STI;
return ExceptionContinueSearch;
}
return ExceptionContinueExecution;
}
return ExceptionContinueSearch; /* Unable to emulate it */
......
......@@ -595,9 +595,11 @@ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
*
* Build a sigcontext from the register values.
*/
static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
static void restore_context( CONTEXT *context, SIGCONTEXT *sigcontext )
{
#ifdef __HAVE_VM86
BOOL check_pending = TRUE;
/* check if exception occurred in vm86 mode */
if ((void *)EIP_sig(sigcontext) == vm86_return &&
IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) &&
......@@ -610,6 +612,43 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
restore_vm86_context( context, vm86 );
return;
}
while (NtCurrentTeb()->dpmi_vif &&
!IS_SELECTOR_SYSTEM(context->SegCs) &&
!IS_SELECTOR_SYSTEM(context->SegSs) &&
check_pending)
{
/*
* Executing DPMI code and virtual interrupts are enabled.
* We must block signals so that we can be safely check
* for pending asynchronous events. Return from signal handler
* will unblock signals again so it is is safe to do so.
*/
SIGNAL_Block();
check_pending = FALSE;
if (NtCurrentTeb()->vm86_pending)
{
EXCEPTION_RECORD rec;
rec.ExceptionAddress = (LPVOID)context->Eip;
rec.ExceptionCode = EXCEPTION_VM86_STI;
rec.ExceptionFlags = EXCEPTION_CONTINUABLE;
rec.ExceptionRecord = NULL;
rec.NumberParameters = 1;
rec.ExceptionInformation[0] = 0;
NtCurrentTeb()->vm86_pending = 0;
EXC_RtlRaiseException( &rec, context );
/*
* EXC_RtlRaiseException has unblocked all signals
* and we must retry check for pending asynchronous
* events in order to prevent races.
*/
check_pending = TRUE;
}
}
#endif /* __HAVE_VM86 */
EAX_sig(sigcontext) = context->Eax;
......@@ -977,22 +1016,6 @@ static void set_vm86_pend( CONTEXT *context )
restore_vm86_context( &vcontext, vm86 );
}
}
else if(teb->dpmi_vif &&
!IS_SELECTOR_SYSTEM(context->SegCs) &&
!IS_SELECTOR_SYSTEM(context->SegSs))
{
/* Executing DPMI code and virtual interrupts are enabled. */
teb->vm86_pending = 0;
rec.ExceptionAddress = (LPVOID)context->Eip;
EXC_RtlRaiseException( &rec, context );
/*
* EXC_RtlRaiseException has unblocked all signals and this
* signal handler is about to return to either DOS relay or
* IRQ handler. Because both of these will check pending
* interrupts again, it is not a problem if we receive
* a nested SIGUSR2 here and ignore it.
*/
}
}
......
......@@ -227,17 +227,6 @@ void DOSVM_SendQueuedEvents( CONTEXT86 *context )
#ifdef MZ_SUPPORTED
if (!ISV86(context) && context->SegCs == old_cs && context->Eip == old_ip)
{
/*
* Routine was called from DPMI but there was nothing to do.
* We force a dummy relay call here so that we don't get a race
* if signals are unblocked when we return to DPMI application.
*/
TRACE( "Called but there was nothing to do, calling NULL relay.\n" );
DOSVM_BuildCallFrame( context, NULL, NULL );
}
if (DOSVM_HasPendingEvents())
{
/*
......
......@@ -157,17 +157,6 @@ void DOSVM_RelayHandler( CONTEXT86 *context )
ERR( "Stack corrupted!\n" );
stack->inuse = 0;
/*
* We have now restored original stack and instruction pointers.
* Because signals are blocked here, this is a safe place to
* check for pending events before we return to application context.
*/
if (NtCurrentTeb()->vm86_pending && NtCurrentTeb()->dpmi_vif)
{
NtCurrentTeb()->vm86_pending = 0;
DOSVM_SendQueuedEvents( context );
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment