-
Notifications
You must be signed in to change notification settings - Fork 269
Http CloseHandle for closing while waiting #331
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,7 +40,7 @@ mod utils; | |||||||||||||||||||||
| mod tests; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| use std::io; | ||||||||||||||||||||||
| use std::sync::{mpsc, Arc}; | ||||||||||||||||||||||
| use std::sync::{mpsc, Arc, Mutex}; | ||||||||||||||||||||||
| use std::net::SocketAddr; | ||||||||||||||||||||||
| use std::thread; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -430,7 +430,7 @@ impl<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>> ServerBuilder<M, S> { | |||||||||||||||||||||
| Ok(Server { | ||||||||||||||||||||||
| address: local_addr?, | ||||||||||||||||||||||
| executor: Some(executors), | ||||||||||||||||||||||
| close: Some(close), | ||||||||||||||||||||||
| close: Arc::new(Mutex::new(Some(close))), | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
@@ -554,7 +554,7 @@ fn configure_port(_reuse: bool, _tcp: &net2::TcpBuilder) -> io::Result<()> { | |||||||||||||||||||||
| pub struct Server { | ||||||||||||||||||||||
| address: SocketAddr, | ||||||||||||||||||||||
| executor: Option<Vec<Executor>>, | ||||||||||||||||||||||
| close: Option<Vec<oneshot::Sender<()>>>, | ||||||||||||||||||||||
| close: Arc<Mutex<Option<Vec<oneshot::Sender<()>>>>>, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const PROOF: &'static str = "Server is always Some until self is consumed."; | ||||||||||||||||||||||
|
|
@@ -566,13 +566,7 @@ impl Server { | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| /// Closes the server. | ||||||||||||||||||||||
| pub fn close(mut self) { | ||||||||||||||||||||||
| for close in self.close.take().expect(PROOF) { | ||||||||||||||||||||||
| let _ = close.send(()); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| for executor in self.executor.take().expect(PROOF) { | ||||||||||||||||||||||
| executor.close(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| self.close_handle().close(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /// Will block, waiting for the server to finish. | ||||||||||||||||||||||
|
|
@@ -581,12 +575,50 @@ impl Server { | |||||||||||||||||||||
| executor.wait(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /// Returns a handle to the server that can be used to close it while another thread is | ||||||||||||||||||||||
| /// blocking in `wait`. | ||||||||||||||||||||||
| pub fn close_handle(&mut self) -> CloseHandle { | ||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function shouldn't mutate anything, so it should be
Suggested change
|
||||||||||||||||||||||
| let executor_close: Option<Vec<_>> = self.executor.as_mut().map(|executors| { | ||||||||||||||||||||||
| executors | ||||||||||||||||||||||
| .iter_mut() | ||||||||||||||||||||||
| .map(|executor| executor.close_handle()) | ||||||||||||||||||||||
| .collect() | ||||||||||||||||||||||
| }); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| CloseHandle { | ||||||||||||||||||||||
| executor_close: Arc::new(Mutex::new(executor_close)), | ||||||||||||||||||||||
| close: self.close.clone(), | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| impl Drop for Server { | ||||||||||||||||||||||
| fn drop(&mut self) { | ||||||||||||||||||||||
| self.executor.take().map(|executors| { | ||||||||||||||||||||||
| for executor in executors { executor.close(); } | ||||||||||||||||||||||
| }); | ||||||||||||||||||||||
| self.close_handle().close(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /// A handle that allows closing of a server even if it owned by a thread blocked in `wait`. | ||||||||||||||||||||||
| #[derive(Clone)] | ||||||||||||||||||||||
| pub struct CloseHandle { | ||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should implement/derive
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. futures::Sender, doesn't implement Clone(), so how should we approach this?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @carllin it's wrapped in
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So let's wrap it into
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tomusdrw, in the current WS implementation, close() also closes the executor: https://github.com/paritytech/jsonrpc/blob/master/ws/src/server.rs#L149 |
||||||||||||||||||||||
| close: Arc<Mutex<Option<Vec<oneshot::Sender<()>>>>>, | ||||||||||||||||||||||
| executor_close: Arc<Mutex<Option<Vec<Option<futures::Complete<()>>>>>>, | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| impl CloseHandle { | ||||||||||||||||||||||
| /// Closes the `Server`. | ||||||||||||||||||||||
| pub fn close(self) { | ||||||||||||||||||||||
| self.close.lock().unwrap().take().map(|close_vector| { | ||||||||||||||||||||||
| for close in close_vector { | ||||||||||||||||||||||
| let _ = close.send(()); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| }); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| self.executor_close.lock().unwrap().take().map(|executor_close_vector| { | ||||||||||||||||||||||
| for e in executor_close_vector { | ||||||||||||||||||||||
| e.map(|v| v.send(())); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| }); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -62,6 +62,15 @@ impl Executor { | |||||
| self.executor().spawn(future) | ||||||
| } | ||||||
|
|
||||||
| /// Returns a handle to close the underlying event loop | ||||||
| pub fn close_handle(&mut self) -> Option<futures::Complete<()>> { | ||||||
tomusdrw marked this conversation as resolved.
Show resolved
Hide resolved
tomusdrw marked this conversation as resolved.
Show resolved
Hide resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if let Executor::Spawned(ref mut eloop) = self { | ||||||
| eloop.close_handle() | ||||||
| } else { | ||||||
| None | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// Closes underlying event loop (if any!). | ||||||
| pub fn close(self) { | ||||||
| if let Executor::Spawned(eloop) = self { | ||||||
|
|
@@ -163,4 +172,10 @@ impl RpcEventLoop { | |||||
| warn!("Event Loop is already finished. {:?}", e); | ||||||
| }); | ||||||
| } | ||||||
|
|
||||||
| /// Returns the close signal that can be used to close the event loop even while | ||||||
| /// another thread is blocked on the event loop in "wait" | ||||||
| pub fn close_handle(&mut self) -> Option<futures::Complete<()>>{ | ||||||
tomusdrw marked this conversation as resolved.
Show resolved
Hide resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function doesn't make much sense - the whole point of handle is to be able to have multiple instance of it. I still believe that having this function is completely unnecessary. See how it's done in |
||||||
| self.close.take() | ||||||
| } | ||||||
| } | ||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
executor should most likely be wrapped in
Arc<Mutex<as wel, so that it can be passed toCloseHandle. Actually it would be simpler to storeCloseHandledirectly inServerand just clone it when requested.CloseHandleshould handle the case ifOptionsareNone.To simplify it further you can just have:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how this would work: once the server starts waiting it has to take the lock on the
handle, soclose()as written above will hang on the lock?