@@ -40,6 +40,8 @@ use std::net::SocketAddr;
4040use std:: sync:: { mpsc, Arc } ;
4141use std:: thread;
4242
43+ use parking_lot:: Mutex ;
44+
4345use crate :: jsonrpc:: futures:: sync:: oneshot;
4446use crate :: jsonrpc:: futures:: { self , future, Future , Stream } ;
4547use crate :: jsonrpc:: MetaIoHandler ;
@@ -377,10 +379,12 @@ impl<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>> ServerBuilder<M, S> {
377379
378380 let ( local_addr_tx, local_addr_rx) = mpsc:: channel ( ) ;
379381 let ( close, shutdown_signal) = oneshot:: channel ( ) ;
382+ let ( done_tx, done_rx) = oneshot:: channel ( ) ;
380383 let eloop = self . executor . init_with_name ( "http.worker0" ) ?;
381384 let req_max_size = self . max_request_body_size ;
385+ // The first threads `Executor` is initialised differently from the others
382386 serve (
383- ( shutdown_signal, local_addr_tx) ,
387+ ( shutdown_signal, local_addr_tx, done_tx ) ,
384388 eloop. executor ( ) ,
385389 addr. to_owned ( ) ,
386390 cors_domains. clone ( ) ,
@@ -399,9 +403,10 @@ impl<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>> ServerBuilder<M, S> {
399403 . map ( |i| {
400404 let ( local_addr_tx, local_addr_rx) = mpsc:: channel ( ) ;
401405 let ( close, shutdown_signal) = oneshot:: channel ( ) ;
406+ let ( done_tx, done_rx) = oneshot:: channel ( ) ;
402407 let eloop = UninitializedExecutor :: Unspawned . init_with_name ( format ! ( "http.worker{}" , i + 1 ) ) ?;
403408 serve (
404- ( shutdown_signal, local_addr_tx) ,
409+ ( shutdown_signal, local_addr_tx, done_tx ) ,
405410 eloop. executor ( ) ,
406411 addr. to_owned ( ) ,
407412 cors_domains. clone ( ) ,
@@ -416,27 +421,34 @@ impl<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>> ServerBuilder<M, S> {
416421 reuse_port,
417422 req_max_size,
418423 ) ;
419- Ok ( ( eloop, close, local_addr_rx) )
424+ Ok ( ( eloop, close, local_addr_rx, done_rx ) )
420425 } )
421426 . collect :: < io:: Result < Vec < _ > > > ( ) ?;
422427
423428 // Wait for server initialization
424429 let local_addr = recv_address ( local_addr_rx) ;
425430 // Wait for other threads as well.
426- let mut handles = handles
431+ let mut handles: Vec < ( Executor , oneshot :: Sender < ( ) > , oneshot :: Receiver < ( ) > ) > = handles
427432 . into_iter ( )
428- . map ( |( eloop, close, local_addr_rx) | {
433+ . map ( |( eloop, close, local_addr_rx, done_rx ) | {
429434 let _ = recv_address ( local_addr_rx) ?;
430- Ok ( ( eloop, close) )
435+ Ok ( ( eloop, close, done_rx ) )
431436 } )
432437 . collect :: < io:: Result < ( Vec < _ > ) > > ( ) ?;
433- handles. push ( ( eloop, close) ) ;
434- let ( executors, close) = handles. into_iter ( ) . unzip ( ) ;
438+ handles. push ( ( eloop, close, done_rx) ) ;
439+
440+ let ( executors, done_rxs) = handles
441+ . into_iter ( )
442+ . fold ( ( vec ! [ ] , vec ! [ ] ) , |mut acc, ( eloop, closer, done_rx) | {
443+ acc. 0 . push ( ( eloop, closer) ) ;
444+ acc. 1 . push ( done_rx) ;
445+ acc
446+ } ) ;
435447
436448 Ok ( Server {
437449 address : local_addr?,
438- executor : Some ( executors) ,
439- close : Some ( close ) ,
450+ executors : Arc :: new ( Mutex :: new ( Some ( executors) ) ) ,
451+ done : Some ( done_rxs ) ,
440452 } )
441453 }
442454}
@@ -448,7 +460,7 @@ fn recv_address(local_addr_rx: mpsc::Receiver<io::Result<SocketAddr>>) -> io::Re
448460}
449461
450462fn serve < M : jsonrpc:: Metadata , S : jsonrpc:: Middleware < M > > (
451- signals : ( oneshot:: Receiver < ( ) > , mpsc:: Sender < io:: Result < SocketAddr > > ) ,
463+ signals : ( oneshot:: Receiver < ( ) > , mpsc:: Sender < io:: Result < SocketAddr > > , oneshot :: Sender < ( ) > ) ,
452464 executor : tokio:: runtime:: TaskExecutor ,
453465 addr : SocketAddr ,
454466 cors_domains : CorsDomains ,
@@ -463,7 +475,7 @@ fn serve<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>>(
463475 reuse_port : bool ,
464476 max_request_body_size : usize ,
465477) {
466- let ( shutdown_signal, local_addr_tx) = signals;
478+ let ( shutdown_signal, local_addr_tx, done_tx ) = signals;
467479 executor. spawn ( future:: lazy ( move || {
468480 let handle = tokio:: reactor:: Handle :: default ( ) ;
469481
@@ -537,12 +549,15 @@ fn serve<M: jsonrpc::Metadata, S: jsonrpc::Middleware<M>>(
537549 . map_err ( |e| {
538550 warn ! ( "Incoming streams error, closing sever: {:?}" , e) ;
539551 } )
540- . select ( shutdown_signal. map_err ( |e| {
552+ . select ( shutdown_signal
553+ . map_err ( |e| {
541554 debug ! ( "Shutdown signaller dropped, closing server: {:?}" , e) ;
542555 } ) )
543556 . map ( |_| ( ) )
544557 . map_err ( |_| ( ) )
545558 } )
559+ } ) . and_then ( |_| {
560+ done_tx. send ( ( ) )
546561 } ) ) ;
547562}
548563
@@ -562,45 +577,60 @@ fn configure_port(_reuse: bool, _tcp: &net2::TcpBuilder) -> io::Result<()> {
562577 Ok ( ( ) )
563578}
564579
580+ /// Handle used to close the server. Can be cloned and passed around to different threads and be used
581+ /// to close a server that is `wait()`ing.
582+
583+ #[ derive( Clone ) ]
584+ pub struct CloseHandle ( Arc < Mutex < Option < Vec < ( Executor , oneshot:: Sender < ( ) > ) > > > > ) ;
585+
586+ impl CloseHandle {
587+ /// Shutdown a running server
588+ pub fn close ( self ) {
589+ if let Some ( executors) = self . 0 . lock ( ) . take ( ) {
590+ for ( executor, closer) in executors {
591+ executor. close ( ) ;
592+ let _ = closer. send ( ( ) ) ;
593+ }
594+ }
595+ }
596+ }
597+
565598/// jsonrpc http server instance
566599pub struct Server {
567600 address : SocketAddr ,
568- executor : Option < Vec < Executor > > ,
569- close : Option < Vec < oneshot:: Sender < ( ) > > > ,
601+ executors : Arc < Mutex < Option < Vec < ( Executor , oneshot :: Sender < ( ) > ) > > > > ,
602+ done : Option < Vec < oneshot:: Receiver < ( ) > > > ,
570603}
571604
572- const PROOF : & str = "Server is always Some until self is consumed." ;
573605impl Server {
574606 /// Returns address of this server
575607 pub fn address ( & self ) -> & SocketAddr {
576608 & self . address
577609 }
578610
579611 /// Closes the server.
580- pub fn close ( mut self ) {
581- for close in self . close . take ( ) . expect ( PROOF ) {
582- let _ = close. send ( ( ) ) ;
583- }
584-
585- for executor in self . executor . take ( ) . expect ( PROOF ) {
586- executor. close ( ) ;
587- }
612+ pub fn close ( self ) {
613+ self . close_handle ( ) . close ( )
588614 }
589615
590616 /// Will block, waiting for the server to finish.
591617 pub fn wait ( mut self ) {
592- for executor in self . executor . take ( ) . expect ( PROOF ) {
593- executor. wait ( ) ;
618+ if let Some ( receivers) = self . done . take ( ) {
619+ for receiver in receivers {
620+ let _ = receiver. wait ( ) ;
621+ }
594622 }
595623 }
624+
625+ /// Get a handle that allows us to close the server from a different thread and/or while the
626+ /// server is `wait()`ing.
627+ pub fn close_handle ( & self ) -> CloseHandle {
628+ CloseHandle ( self . executors . clone ( ) )
629+ }
596630}
597631
598632impl Drop for Server {
599633 fn drop ( & mut self ) {
600- if let Some ( executors) = self . executor . take ( ) {
601- for executor in executors {
602- executor. close ( ) ;
603- }
604- } ;
634+ self . close_handle ( ) . close ( ) ;
605635 }
606636}
0 commit comments