New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session in 0.4.0 no longer Send #137
Comments
It actually is more complicated to make I'm getting these errors when I try to wrap my modified version of
and
|
I overlooked that we used to add This is how I'm "dealing" with this in one of my applications: Would you mind sharing a bit more about how you'd like to use ssh2 here? From the example you linked you have a global protected by a Mutex; is that actually how you'd like to use this crate, or just something you're trying to get things to work? The reason I ask is because I think that it might make sense to offer a couple of different submodules/structs that wrap the library primitives in a more task-focused way; by knowing more about the use cases, we can expose the right API surfaces more egonomically and deal with some of the thread safety concerns internally. |
My use case is probably very unusual, the reason for that beeing that I'm farily new to rust and also have to interact with a C application (Zabbix) that has some strange ways to deal with things. I don't actually deal with multithreading in the application, instead only multiprocessing exists. But since I'm only writing a lodable module for Zabbix I just get called from it and don't have any good way to keep state across beeing called other than globals. So what I'm doing is putting the What would really be nice would be having a Struct already provided that owns both the Edit: I just looked over 0.4.0 some more, and Edit 2: Some documentation dosen't reflect that change: https://github.com/alexcrichton/ssh2-rs/blob/master/src/session.rs#L93 |
Thanks for the info on your use case! Since I'm traveling at the moment I thought it would be best for the sake of expediency to just make this |
Thanks for the fast response! I'm wondering tho why it is safe to tell the compiler that |
@usbpc https://doc.rust-lang.org/std/net/struct.TcpStream.html is @wez Any chance of a similar change for I'm writing an SSH client which has multiple threads, and I can't pass the different channels to different threads, to handle read and writing TCP connections:
|
Oh, and Listener? |
It's not automatically safe to add an What I'd suggest for now is that you wrap things up in a struct of your own and tell the compiler that your use case is safe by doing something like this: https://github.com/wez/wezterm/blob/master/pty/src/ssh.rs#L45-L49 |
Can't you create this unsafety by passing the Session into a thread (as Session is Send), creating a Channel, and then repeating? Sent with GitHawk |
What we really need to do here is one of the two things:
In the later case, the definition of pub(crate) struct SessionInner {
pub(crate) raw: *mut raw::LIBSSH2_SESSION,
- tcp: RefCell<Option<TcpStream>>,
}
unsafe impl Send for SessionInner {}
pub struct Session {
- inner: Arc<SessionInner>,
+ inner: Arc<Mutex<SessionInner>>,
+ tcp: Option<TcpStream>,
}
-unsafe impl Send for Session {} Here, the reason for wrapping |
In earlier iterations I accidentally removed Send from Session and then later restored it in an unsafe way. This commit restructures the bindings so that each of the objects holds a reference to the appropriate thing to keep everything alive safely, without awkward lifetimes to deal with. The key to this is that the underlying Session is tracked by an Arc<Mutex<>>, with the related objects ensuring that they lock this before they call into the underlying API. In order to make this work, I've had to adjust the API around iterating both known hosts and agent identities: previously these would iterate over internal references but with this shift there isn't a reasonable way to make that safe. The strategy is instead to return a copy of the host/identity data and then later look up the associated raw pointer when needed. The purist in me feels that the copy feels slightly wasteful, but the realist justifies this with the observation that the cardinality of both known hosts and identities is typically small enough that the cost of this is in the noise compared to actually doing the crypto+network ops. I've removed a couple of error code related helpers from some of the objects: those were really internal APIs and were redundant with methods exported by the Error type anyway. Fixes: #154 Refs: #137
We're now Send + Sync for everything in 0.7.0 which I released to crates.io just now |
In version 0.3.3 the Session struct implemented the
Send
trait unfortunately since in 0.4.0 it's using astd::rc::Rc
to store theSessionInner
,std::rc::Rc
is very explicitly notSend
, therefore thessh2::Session
struct is no longer implementing theSend
trait.Changing the
std::rc::Rc
to astd::sync::Arc
should solve the Problem without a huge performance impact. The Change would need to be made here:https://github.com/alexcrichton/ssh2-rs/blob/master/src/session.rs#L79
The text was updated successfully, but these errors were encountered: