about summary refs log tree commit diff
path: root/src/libstd/comm
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/comm')
-rw-r--r--src/libstd/comm/mod.rs22
-rw-r--r--src/libstd/comm/shared.rs14
2 files changed, 23 insertions, 13 deletions
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
index b2521f2978a..18857e221fa 100644
--- a/src/libstd/comm/mod.rs
+++ b/src/libstd/comm/mod.rs
@@ -600,20 +600,22 @@ impl<T: Send> Clone for Sender<T> {
         let (packet, sleeper) = match *unsafe { self.inner() } {
             Oneshot(ref p) => {
                 let a = Arc::new(Unsafe::new(shared::Packet::new()));
-                match unsafe {
-                    (*p.get()).upgrade(Receiver::new(Shared(a.clone())))
-                } {
-                    oneshot::UpSuccess | oneshot::UpDisconnected => (a, None),
-                    oneshot::UpWoke(task) => (a, Some(task))
+                unsafe {
+                    (*a.get()).postinit_lock();
+                    match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
+                        oneshot::UpSuccess | oneshot::UpDisconnected => (a, None),
+                        oneshot::UpWoke(task) => (a, Some(task))
+                    }
                 }
             }
             Stream(ref p) => {
                 let a = Arc::new(Unsafe::new(shared::Packet::new()));
-                match unsafe {
-                    (*p.get()).upgrade(Receiver::new(Shared(a.clone())))
-                } {
-                    stream::UpSuccess | stream::UpDisconnected => (a, None),
-                    stream::UpWoke(task) => (a, Some(task)),
+                unsafe {
+                    (*a.get()).postinit_lock();
+                    match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
+                        stream::UpSuccess | stream::UpDisconnected => (a, None),
+                        stream::UpWoke(task) => (a, Some(task)),
+                    }
                 }
             }
             Shared(ref p) => {
diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs
index 8aef2ec80a8..3fde584a46f 100644
--- a/src/libstd/comm/shared.rs
+++ b/src/libstd/comm/shared.rs
@@ -66,7 +66,8 @@ pub enum Failure {
 }
 
 impl<T: Send> Packet<T> {
-    // Creation of a packet *must* be followed by a call to inherit_blocker
+    // Creation of a packet *must* be followed by a call to postinit_lock
+    // and later by inherit_blocker
     pub fn new() -> Packet<T> {
         let p = Packet {
             queue: mpsc::Queue::new(),
@@ -78,11 +79,18 @@ impl<T: Send> Packet<T> {
             sender_drain: atomics::AtomicInt::new(0),
             select_lock: unsafe { NativeMutex::new() },
         };
-        // see comments in inherit_blocker about why we grab this lock
-        unsafe { p.select_lock.lock_noguard() }
         return p;
     }
 
+    // This function should be used after newly created Packet
+    // was wrapped with an Arc
+    // In other case mutex data will be duplicated while clonning
+    // and that could cause problems on platforms where it is
+    // represented by opaque data structure
+    pub fn postinit_lock(&mut self) {
+        unsafe { self.select_lock.lock_noguard() }
+    }
+
     // This function is used at the creation of a shared packet to inherit a
     // previously blocked task. This is done to prevent spurious wakeups of
     // tasks in select().