[project @ 2003-02-08 13:34:06 by wolfgang]
authorwolfgang <unknown>
Sat, 8 Feb 2003 13:34:06 +0000 (13:34 +0000)
committerwolfgang <unknown>
Sat, 8 Feb 2003 13:34:06 +0000 (13:34 +0000)
Fix a potential crash in the threaded RTS by copying ccall arguments
from the TSO stack to a malloced block before doing the call.
(no changes were made for the non-threaded case)

ghc/rts/Interpreter.c

index 270feb0..79b883b 100644 (file)
@@ -1157,8 +1157,19 @@ run_BCO:
            int stk_offset            = BCO_NEXT;
            int o_itbl                = BCO_NEXT;
            void(*marshall_fn)(void*) = (void (*)(void*))BCO_LIT(o_itbl);
-           StgTSO *tso               = cap->r.rCurrentTSO;
 
+#ifdef RTS_SUPPORTS_THREADS
+           // Threaded RTS:
+           // Arguments on the TSO stack are not good, because garbage
+           // collection might move the TSO as soon as we call
+           // suspendThread below.
+
+           void *arguments;
+           
+           arguments = stgMallocWords(stk_offset,"bci_CCALL");
+           memcpy(arguments, Sp, sizeof(W_) * stk_offset);
+#endif
+               
            // There are a bunch of non-ptr words on the stack (the
            // ccall args, the ccall fun address and space for the
            // result), which we need to cover with an info table
@@ -1176,21 +1187,35 @@ run_BCO:
            SAVE_STACK_POINTERS;
            tok = suspendThread(&cap->r,rtsFalse);
 
+#ifndef RTS_SUPPORTS_THREADS
            // Careful:
            // suspendThread might have shifted the stack
            // around (stack squeezing), so we have to grab the real
            // Sp out of the TSO to find the ccall args again.
-           // We don't own the capability anymore, so we mustn't use it.
-           // Instead, we have to save the TSO ptr beforehand.
-           // Also note that GC may strike at any time now (from another thread).
-           // FIXME - DANGER!! Can GC move our TSO?
-           // If so, we have to copy the args elsewhere!
-           marshall_fn ( (void*)(tso->sp + RET_DYN_SIZE + sizeofW(StgRetDyn)) );
-                   
+
+           marshall_fn ( (void*)(cap->r.rCurrentTSO->sp + RET_DYN_SIZE + sizeofW(StgRetDyn)) );
+#else
+           // Threaded RTS:
+           // We already made a malloced copy of the arguments above.
+
+           marshall_fn ( arguments );
+#endif
+
            // And restart the thread again, popping the RET_DYN frame.
            cap = (Capability *)((void *)resumeThread(tok,rtsFalse) - sizeof(StgFunTable));
            LOAD_STACK_POINTERS;
            Sp += RET_DYN_SIZE + sizeofW(StgRetDyn);
+
+           
+#ifdef RTS_SUPPORTS_THREADS
+           // Threaded RTS:
+           // Copy the "arguments", which might include a return value,
+           // back to the TSO stack. It would of course be enough to
+           // just copy the return value, but we don't know the offset.
+           memcpy(Sp, arguments, sizeof(W_) * stk_offset);
+           free(arguments);
+#endif
+
            goto nextInsn;
        }