mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 19:49:50 +00:00
Remove races from DPMI async event handling.
This commit is contained in:
parent
9b4b21b7b0
commit
46f29944c3
4 changed files with 40 additions and 45 deletions
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue