guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 42/58: vm: Fix stack-marking bug in multi-threaded progr


From: Andy Wingo
Subject: [Guile-commits] 42/58: vm: Fix stack-marking bug in multi-threaded programs.
Date: Tue, 7 Aug 2018 06:58:37 -0400 (EDT)

wingo pushed a commit to branch lightning
in repository guile.

commit 8840ee5a3ca48e1fc6b58c036467118ddf4dfcc4
Author: Ludovic Courtès <address@hidden>
Date:   Fri Jun 29 22:28:48 2018 +0200

    vm: Fix stack-marking bug in multi-threaded programs.
    
    Fixes <https://bugs.gnu.org/28211>.
    
    * libguile/vm-engine.c (call, call_label, handle_interrupts): Add
    'new_fp' variable; set the dynamic link and return address of the frame
    at NEW_FP before setting 'vp->fp'.  This fixes a bug whereby, in a
    multi-threaded context, the stack-marking code could run after vp->fp
    has been set but before its dynamic link has been set, leading the
    stack-walking code in 'scm_i_vm_mark_stack' to exit early on.
---
 libguile/vm-engine.c | 34 ++++++++++++++++++++--------------
 libguile/vm.c        | 14 ++++++++------
 2 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 7305bee..4b55906 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -324,6 +324,7 @@ VM_NAME (scm_thread *thread)
       /* Boot closure in r0, empty frame in r1/r2, proc in r3, values from r4. 
 */
 
       uint32_t nvals = FRAME_LOCALS_COUNT_FROM (4);
+      union scm_vm_stack_element *fp;
       SCM ret;
 
       if (nvals == 1)
@@ -338,9 +339,10 @@ VM_NAME (scm_thread *thread)
             SCM_SET_CELL_OBJECT (ret, n+1, FP_REF (4 + n));
         }
 
-      VP->ip = SCM_FRAME_RETURN_ADDRESS (VP->fp);
-      VP->sp = SCM_FRAME_PREVIOUS_SP (VP->fp);
-      VP->fp = SCM_FRAME_DYNAMIC_LINK (VP->fp);
+      fp = VP->fp;
+      VP->fp = SCM_FRAME_DYNAMIC_LINK (fp);
+      VP->ip = SCM_FRAME_RETURN_ADDRESS (fp);
+      VP->sp = SCM_FRAME_PREVIOUS_SP (fp);
 
       return ret;
     }
@@ -361,7 +363,7 @@ VM_NAME (scm_thread *thread)
   VM_DEFINE_OP (1, call, "call", OP2 (X8_F24, X8_C24))
     {
       uint32_t proc, nlocals;
-      union scm_vm_stack_element *old_fp;
+      union scm_vm_stack_element *old_fp, *new_fp;
 
       UNPACK_24 (op, proc);
       UNPACK_24 (ip[1], nlocals);
@@ -369,9 +371,10 @@ VM_NAME (scm_thread *thread)
       PUSH_CONTINUATION_HOOK ();
 
       old_fp = VP->fp;
-      VP->fp = SCM_FRAME_SLOT (old_fp, proc - 1);
-      SCM_FRAME_SET_DYNAMIC_LINK (VP->fp, old_fp);
-      SCM_FRAME_SET_RETURN_ADDRESS (VP->fp, ip + 2);
+      new_fp = SCM_FRAME_SLOT (old_fp, proc - 1);
+      SCM_FRAME_SET_DYNAMIC_LINK (new_fp, old_fp);
+      SCM_FRAME_SET_RETURN_ADDRESS (new_fp, ip + 2);
+      VP->fp = new_fp;
 
       RESET_FRAME (nlocals);
 
@@ -403,7 +406,7 @@ VM_NAME (scm_thread *thread)
     {
       uint32_t proc, nlocals;
       int32_t label;
-      union scm_vm_stack_element *old_fp;
+      union scm_vm_stack_element *old_fp, *new_fp;
 
       UNPACK_24 (op, proc);
       UNPACK_24 (ip[1], nlocals);
@@ -412,9 +415,10 @@ VM_NAME (scm_thread *thread)
       PUSH_CONTINUATION_HOOK ();
 
       old_fp = VP->fp;
-      VP->fp = SCM_FRAME_SLOT (old_fp, proc - 1);
-      SCM_FRAME_SET_DYNAMIC_LINK (VP->fp, old_fp);
-      SCM_FRAME_SET_RETURN_ADDRESS (VP->fp, ip + 3);
+      new_fp = SCM_FRAME_SLOT (old_fp, proc - 1);
+      SCM_FRAME_SET_DYNAMIC_LINK (new_fp, old_fp);
+      SCM_FRAME_SET_RETURN_ADDRESS (new_fp, ip + 3);
+      VP->fp = new_fp;
 
       RESET_FRAME (nlocals);
 
@@ -2387,9 +2391,11 @@ VM_NAME (scm_thread *thread)
    */
   VM_DEFINE_OP (184, return_from_interrupt, "return-from-interrupt", OP1 (X32))
     {
-      VP->sp = sp = SCM_FRAME_PREVIOUS_SP (VP->fp);
-      ip = SCM_FRAME_RETURN_ADDRESS (VP->fp);
-      VP->fp = SCM_FRAME_DYNAMIC_LINK (VP->fp);
+      union scm_vm_stack_element *fp = VP->fp;
+
+      ip = SCM_FRAME_RETURN_ADDRESS (fp);
+      VP->fp = SCM_FRAME_DYNAMIC_LINK (fp);
+      VP->sp = sp = SCM_FRAME_PREVIOUS_SP (fp);
 
       NEXT (0);
     }
diff --git a/libguile/vm.c b/libguile/vm.c
index fa2f171..cc95a2c 100644
--- a/libguile/vm.c
+++ b/libguile/vm.c
@@ -1013,7 +1013,7 @@ cons_rest (scm_thread *thread, uint32_t base)
 static void
 push_interrupt_frame (scm_thread *thread)
 {
-  union scm_vm_stack_element *old_fp;
+  union scm_vm_stack_element *old_fp, *new_fp;
   size_t old_frame_size = frame_locals_count (thread);
   SCM proc = scm_i_async_pop (thread);
 
@@ -1024,13 +1024,14 @@ push_interrupt_frame (scm_thread *thread)
   alloc_frame (thread, old_frame_size + 3);
 
   old_fp = thread->vm.fp;
-  thread->vm.fp = SCM_FRAME_SLOT (old_fp, old_frame_size + 1);
-  SCM_FRAME_SET_DYNAMIC_LINK (thread->vm.fp, old_fp);
+  new_fp = SCM_FRAME_SLOT (old_fp, old_frame_size + 1);
+  SCM_FRAME_SET_DYNAMIC_LINK (new_fp, old_fp);
   /* Arrange to return to the same handle-interrupts opcode to handle
      any additional interrupts.  */
-  SCM_FRAME_SET_RETURN_ADDRESS (thread->vm.fp, thread->vm.ip);
+  SCM_FRAME_SET_RETURN_ADDRESS (new_fp, thread->vm.ip);
+  SCM_FRAME_LOCAL (new_fp, 0) = proc;
 
-  SCM_FRAME_LOCAL (thread->vm.fp, 0) = proc;
+  thread->vm.fp = new_fp;
 }
 
 struct return_to_continuation_data
@@ -1402,7 +1403,6 @@ scm_call_n (SCM proc, SCM *argv, size_t nargs)
   SCM_FRAME_LOCAL (return_fp, 0) = vm_boot_continuation;
 
   vp->ip = (uint32_t *) vm_boot_continuation_code;
-  vp->fp = call_fp;
 
   SCM_FRAME_SET_RETURN_ADDRESS (call_fp, vp->ip);
   SCM_FRAME_SET_DYNAMIC_LINK (call_fp, return_fp);
@@ -1410,6 +1410,8 @@ scm_call_n (SCM proc, SCM *argv, size_t nargs)
   for (i = 0; i < nargs; i++)
     SCM_FRAME_LOCAL (call_fp, i + 1) = argv[i];
 
+  vp->fp = call_fp;
+
   {
     jmp_buf registers;
     int resume;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]