about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2013-08-01 21:57:58 -0400
committerBen Blum <bblum@andrew.cmu.edu>2013-08-02 17:31:44 -0400
commitcde6ad39920ddadd7c70921232ae92adff258367 (patch)
tree242bfb44453dd28dbcc0614cb3efbb394025b413 /src/libstd
parentbe7738bfa18989438e3597847cd6a7f3bbbfac12 (diff)
downloadrust-cde6ad39920ddadd7c70921232ae92adff258367.tar.gz
rust-cde6ad39920ddadd7c70921232ae92adff258367.zip
Fix nasty double-free bug where a newrt chan could get killed after rescheduling but before suppressing_finalize.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/rt/comm.rs9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs
index c19ac8aa337..a060059f5fc 100644
--- a/src/libstd/rt/comm.rs
+++ b/src/libstd/rt/comm.rs
@@ -131,6 +131,13 @@ impl<T> ChanOne<T> {
             // acquire barrier that keeps the subsequent access of the
             // ~Task pointer from being reordered.
             let oldstate = (*packet).state.swap(STATE_ONE, SeqCst);
+
+            // Suppress the synchronizing actions in the finalizer. We're
+            // done with the packet. NB: In case of do_resched, this *must*
+            // happen before waking up a blocked task (or be unkillable),
+            // because we might get a kill signal during the reschedule.
+            this.suppress_finalize = true;
+
             match oldstate {
                 STATE_BOTH => {
                     // Port is not waiting yet. Nothing to do
@@ -165,8 +172,6 @@ impl<T> ChanOne<T> {
             }
         }
 
-        // Suppress the synchronizing actions in the finalizer. We're done with the packet.
-        this.suppress_finalize = true;
         return recvr_active;
     }
 }