winedos / Fix DMPI async event handling regressions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch should make DPMI async event handling
race-free again after instruction emulation changes
which caused instruction emulation to happen 
with all signals unblocked.

Event handling actually gets simpler because there
will be only one place where EXCEPTION_VM86_STI
will be raised. However, signal return path
gets slightly more complicated.

V86 signal handling is still somewhat broken and
probably unnecessarily complicated but that is 
something I'm not going to fix for a while.




Changelog:
    Remove races from DPMI async event handling.




Index: dlls/ntdll/signal_i386.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/signal_i386.c,v
retrieving revision 1.71
diff -u -r1.71 signal_i386.c
--- dlls/ntdll/signal_i386.c	8 Oct 2003 22:59:22 -0000	1.71
+++ dlls/ntdll/signal_i386.c	11 Oct 2003 17:44:51 -0000
@@ -595,9 +595,11 @@
  *
  * 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 @@
         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;
@@ -976,22 +1015,6 @@
             teb->vm86_ptr = vm86;
             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.
-         */
     }
 }
 




Index: dlls/winedos/relay.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/relay.c,v
retrieving revision 1.5
diff -u -r1.5 relay.c
--- dlls/winedos/relay.c	27 Aug 2003 02:52:18 -0000	1.5
+++ dlls/winedos/relay.c	11 Oct 2003 17:44:57 -0000
@@ -157,17 +157,6 @@
         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 );
-    }
 }
 
 




Index: dlls/kernel/instr.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/instr.c,v
retrieving revision 1.3
diff -u -r1.3 instr.c
--- dlls/kernel/instr.c	17 Sep 2003 22:45:46 -0000	1.3
+++ dlls/kernel/instr.c	11 Oct 2003 17:45:04 -0000
@@ -779,12 +779,6 @@
         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 */




Index: dlls/winedos/dosvm.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosvm.c,v
retrieving revision 1.53
diff -u -r1.53 dosvm.c
--- dlls/winedos/dosvm.c	30 Sep 2003 00:22:12 -0000	1.53
+++ dlls/winedos/dosvm.c	11 Oct 2003 17:45:10 -0000
@@ -227,17 +227,6 @@
 
 #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())
     {
         /*



-- 
Jukka Heinonen <http://www.iki.fi/jhei/>


[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux