Finalizing a GSocketConnection closes it even if there's still a reference to its input/output stream
See https://github.com/gtk-rs/gio/issues/195
Minimalized Rust code to reproduce it would be
use gio::prelude::*;
fn main() {
let client = gio::SocketClient::new();
client.set_timeout(10);
let conn = client.connect_to_host("192.30.253.112", 80, None::<&gio::Cancellable>).unwrap();
println!("Is connected: {}", &conn.is_connected());
println!("Stream is closed: {}", &conn.is_closed());
let writer = conn.get_output_stream().expect("Failed to obtain output stream");
// comment this out to make it work
drop(conn);
match writer.write_all(b"test", None::<&gio::Cancellable>) {
Ok((count, _)) => println!("Write finished: {}", count),
Err(err) => println!("Write failed: {}", err),
}
}
This is basically 1:1 what this would be in C except for the memory management.
The problem here is that writer
(the GOutputStream
, a strong reference to one) is kept alive and being written to after conn
(the GSocketConnection
) is dropped (i.e. g_object_unref()
, and this was the one and only reference to it) and finalized. g_io_stream_dispose()
is then calling g_io_stream_close()
, which closes the input/output streams and the writing then fails with "Stream is already closed"
This is relatively unintuitive behaviour.
Should the GSocketConnection
be kept alive by its input/output streams?
Or should this simply be documented somewhere as expected but surprising behaviour?