Failed asserting on Select drop
This is reproduce able 100% with the following code. Looking at the disassembly the problem is that one of the handles drop function is called after the select drop is called.
use std::comm::{Port, Chan, Select};
fn wait_commands(cmd: &mut Port<Port<()>>, ports: &mut ~[Port<()>]) -> Port<()>
{
let mut handles = ~[];
let select = Select::new();
let mut cmd_handle = select.add(cmd);
for port in ports.mut_iter() {
handles.push(select.add(port));
}
loop {
let id = select.wait();
if id == cmd_handle.id {
let port = cmd_handle.recv();
println!("{:?}", port);
return port;
}
for h in handles.mut_iter() {
if h.id == id {
break;
}
}
}
}
fn thread(cmd: Port<Port<()>>)
{
let mut cmd = cmd;
let mut ports: ~[Port<()>] = ~[];
loop {
let port = wait_commands(&mut cmd, &mut ports);
println!("{:?}", port);
ports.push(port);
}
}
fn main()
{
let (p, c) = Chan::new();
spawn(proc() {
thread(p);
});
let (new_p0, new_c0): (Port<()>, Chan<()>) = Chan::new();
let (new_p1, new_c1): (Port<()>, Chan<()>) = Chan::new();
c.send(new_p0);
c.send(new_p1);
new_c0.send(());
new_c1.send(());
}
output
std::comm::Port<()>{queue: SPSC(std::sync::spsc_queue::Consumer<(),std::comm::Packet>{state: std::sync::arc::UnsafeArc<std::sync::spsc_queue::State<(),std::comm::Packet>>{data: (0x7f435c001640 as *mut ())}}), marker: std::kinds::marker::NoFreeze}
std::comm::Port<()>{queue: SPSC(std::sync::spsc_queue::Consumer<(),std::comm::Packet>{state: std::sync::arc::UnsafeArc<std::sync::spsc_queue::State<(),std::comm::Packet>>{data: (0x7f435c001640 as *mut ())}}), marker: std::kinds::marker::NoFreeze}
std::comm::Port<()>{queue: SPSC(std::sync::spsc_queue::Consumer<(),std::comm::Packet>{state: std::sync::arc::UnsafeArc<std::sync::spsc_queue::State<(),std::comm::Packet>>{data: (0x7f435c001740 as *mut ())}}), marker: std::kinds::marker::NoFreeze}
task '<unnamed>' failed at 'assertion failed: self.head.is_null()', /build/buildd/rust-nightly-201402020405~3e39e3e~precise/src/libstd/comm/select.rs:298
My previous thoughts about destructors are not providing the soundness that I thought I was getting. I would expect code like this to not compile:
struct Foo { a: int } struct Bar<'a> { a: &'a Foo, } impl Drop for Foo { fn drop(&mut self) { println!("dropping foo"); } } #[unsafe_destructor] impl<'a> Drop for Bar<'a> { fn drop(&mut self) { println!("dropping bar {}", self.a.a); } } fn main() { let mut a = ~[]; let b = Foo { a: 2 }; a.push(Bar { a: &b }); }The output is
dropping foo dropping bar 2Which is clearly a use-after-free. I presume that this is why I had to write
#[unsafe_destructor]. If you re-orderlet mut handles = ~[]; let select = Select::new();to
let select = Select::new(); let mut handles = ~[];your code should work alright.
cc @nikomatsakis, just want to make sure that this isn't an unknown bug in destructors right now. Also, could any of the new marker types help me with this bug?
Alex Crichton at 2014-02-06 00:51:02
Nominating.
Alex Crichton at 2014-02-06 02:48:38
This is why you had to write unsafe destructor. This is not an unknown bug -- you should never write unsafe destructor on a type that "escapes" to the wild. It is only valid if you control exactly where that type is instantiated. #8861 would possibly help here.
Niko Matsakis at 2014-02-06 15:36:08
Not a 1.0 blocker, P-low. #8861 subsumes the high priority dtor semanitcs issue implicit here.
Felix S Klock II at 2014-02-06 18:47:25
If this is superseded by #8861, can it be closed? It seems like this is mostly a mistake and not really a bug.
Jonathan Reem at 2014-08-08 04:43:19
man this is some old code in this example I need to forward port here!
Felix S Klock II at 2015-02-14 08:13:59
Okay, here is my attempt to forward port the original code: http://is.gd/kk3Fb9
It now produces an error that
selectdoes not live long enough.And if you do the suggested rewrite from https://github.com/rust-lang/rust/issues/12042#issuecomment-34280866 illustrated here: http://is.gd/aSNKtF then it compiles (and times out in the playpen)! Score one for #8861! It only took us a year to get there!
So, i am closing.
Felix S Klock II at 2015-02-14 08:38:06