Skip to content

Commit 138d9ca

Browse files
committed
Drop enqueued elements when a port is destructed. Closes #1155
1 parent 3cc2641 commit 138d9ca

File tree

7 files changed

+39
-2
lines changed

7 files changed

+39
-2
lines changed

src/lib/comm.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ native "cdecl" mod rustrt {
4545
fn new_port(unit_sz: uint) -> *rust_port;
4646
fn del_port(po: *rust_port);
4747
fn get_port_id(po: *rust_port) -> port_id;
48+
fn rust_port_size(po: *rust_port) -> ctypes::size_t;
4849
}
4950

5051
native "rust-intrinsic" mod rusti {
@@ -75,7 +76,13 @@ tag chan<uniq T> {
7576
chan_t(task::task, port_id);
7677
}
7778

78-
resource port_ptr(po: *rustrt::rust_port) {
79+
resource port_ptr<uniq T>(po: *rustrt::rust_port) {
80+
// Drain the port so that all the still-enqueued items get dropped
81+
while rustrt::rust_port_size(po) > 0u {
82+
// FIXME: For some reason if we don't assign to something here
83+
// we end up with invalid reads in the drop glue.
84+
let t = rusti::recv::<T>(po);
85+
}
7986
rustrt::del_port(po);
8087
}
8188

@@ -90,7 +97,7 @@ transmitted. If a port value is copied, both copies refer to the same port.
9097
9198
Ports may be associated with multiple <chan>s.
9299
*/
93-
tag port<uniq T> { port_t(@port_ptr); }
100+
tag port<uniq T> { port_t(@port_ptr<T>); }
94101

95102
/*
96103
Function: send

src/rt/rust_builtin.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,11 @@ del_port(rust_port *port) {
475475
port->deref();
476476
}
477477

478+
extern "C" CDECL size_t
479+
rust_port_size(rust_port *port) {
480+
return port->size();
481+
}
482+
478483
extern "C" CDECL rust_port_id
479484
get_port_id(rust_port *port) {
480485
return port->id;

src/rt/rust_port.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ bool rust_port::receive(void *dptr) {
4848
return false;
4949
}
5050

51+
size_t rust_port::size() {
52+
scoped_lock with(lock);
53+
return buffer.size();
54+
}
55+
5156
void rust_port::log_state() {
5257
LOG(task, comm,
5358
"port size: %d",

src/rt/rust_port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class rust_port : public kernel_owned<rust_port>, public rust_cond {
1919
void log_state();
2020
void send(void *sptr);
2121
bool receive(void *dptr);
22+
size_t size();
2223
};
2324

2425
//

src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ rust_get_stdout
3434
rust_get_stderr
3535
rust_str_push
3636
rust_list_files
37+
rust_port_size
3738
rust_process_wait
3839
rust_ptr_eq
3940
rust_run_program
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// xfail-win32 Requires unwinding
2+
use std;
3+
import std::comm;
4+
5+
fn main() {
6+
let p = comm::port();
7+
let c = comm::chan(p);
8+
comm::send(c, "coffee");
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// xfail-win32 Requires unwinding
2+
use std;
3+
import std::comm;
4+
5+
fn main() {
6+
let p = comm::port();
7+
let c = comm::chan(p);
8+
comm::send(c, ~"coffee");
9+
}

0 commit comments

Comments
 (0)