Skip to content

Commit

Permalink
Drop the previous reference when receiving. Closes #763
Browse files Browse the repository at this point in the history
  • Loading branch information
brson committed Jul 29, 2011
1 parent bf99573 commit 3896524
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 8 deletions.
23 changes: 18 additions & 5 deletions src/comp/middle/trans_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,19 +229,32 @@ fn trans_send(cx: &@block_ctxt, lhs: &@ast::expr, rhs: &@ast::expr,
fn trans_recv(cx: &@block_ctxt, lhs: &@ast::expr, rhs: &@ast::expr,
id: ast::node_id) -> result {
let bcx = cx;
let data = trans_lval(bcx, rhs);
assert (data.is_mem);
bcx = data.res.bcx;
// FIXME: calculate copy init-ness in typestate.

let unit_ty = node_id_type(cx.fcx.lcx.ccx, id);
let tmp_alloc = alloc_ty(bcx, unit_ty);
bcx = tmp_alloc.bcx;

let prt = trans_expr(bcx, lhs);
bcx = prt.bcx;
let lldataptr = bcx.build.PointerCast(data.res.val, T_ptr(T_ptr(T_i8())));
let lldataptr = bcx.build.PointerCast(tmp_alloc.val,
T_ptr(T_ptr(T_i8())));
let llportptr = bcx.build.PointerCast(prt.val, T_opaque_port_ptr());
bcx.build.Call(bcx.fcx.lcx.ccx.upcalls.recv,
~[bcx.fcx.lltaskptr, lldataptr, llportptr]);

ret rslt(bcx, data.res.val);
let tmp = load_if_immediate(bcx, tmp_alloc.val, unit_ty);

let data = trans_lval(bcx, rhs);
assert (data.is_mem);
bcx = data.res.bcx;

let tmp_lval = lval_val(bcx, tmp);

let recv_res =
move_val(bcx, DROP_EXISTING, data.res.val, tmp_lval, unit_ty);

ret rslt(recv_res.bcx, recv_res.val);
}

// Does a deep copy of a value. This is needed for passing arguments to child
Expand Down
36 changes: 36 additions & 0 deletions src/test/run-pass/chan-leak.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Issue #763

use std;
import std::task;

tag request {
quit;
close(chan[bool]);
}

type ctx = chan[request];

fn request_task(c: chan[ctx]) {
let p: port[request] = port();
c <| chan(p);
let req: request;
p |> req;
// Need to drop req before receiving it again
p |> req;
}

fn new() -> ctx {
let p: port[ctx] = port();
let t = spawn request_task(chan(p));
let cx: ctx;
p |> cx;
ret cx;
}

fn main() {
let cx = new();

let p: port[bool] = port();
cx <| close(chan(p));
cx <| quit;
}
5 changes: 2 additions & 3 deletions src/test/run-pass/task-comm-10.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ import std::task;
fn start(c: chan[chan[str]]) {
let p: port[str];

let a;
let b;
p = port();
c <| chan(p);
p |> a;
log_err a;
p |> b;
log_err b;

let a;
let b;
}

fn main() {
Expand Down

0 comments on commit 3896524

Please sign in to comment.