2018-05-09 08:47:21 +02:00
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
2016-02-05 13:40:41 +01:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-01-27 17:18:38 +01:00
//! Ethcore client application.
#![ warn(missing_docs) ]
2016-04-21 13:12:43 +02:00
2018-07-05 15:27:34 +02:00
extern crate parity_ethereum ;
2018-05-09 08:47:21 +02:00
2017-02-13 16:38:47 +01:00
extern crate ctrlc ;
2017-12-24 09:34:43 +01:00
extern crate dir ;
2016-02-05 13:49:36 +01:00
extern crate fdlimit ;
2017-07-06 11:36:15 +02:00
#[ macro_use ]
2018-05-09 08:47:21 +02:00
extern crate log ;
2017-07-03 07:31:29 +02:00
extern crate panic_hook ;
2018-05-09 08:47:21 +02:00
extern crate parking_lot ;
2016-01-20 04:19:38 +01:00
2017-03-23 13:25:31 +01:00
#[ cfg(windows) ] extern crate winapi ;
2016-07-25 16:09:47 +02:00
use std ::{ process , env } ;
2018-07-02 11:53:50 +02:00
use std ::sync ::atomic ::{ AtomicBool , Ordering } ;
2018-05-09 08:47:21 +02:00
use std ::io ::{ self as stdio , Read , Write } ;
2017-03-23 13:25:31 +01:00
use std ::fs ::{ remove_file , metadata , File , create_dir_all } ;
2016-12-10 23:58:39 +01:00
use std ::path ::PathBuf ;
2018-05-09 08:47:21 +02:00
use std ::sync ::Arc ;
use ctrlc ::CtrlC ;
2016-12-15 19:53:13 +01:00
use dir ::default_hypervisor_path ;
2018-05-09 08:47:21 +02:00
use fdlimit ::raise_fd_limit ;
2018-07-05 15:27:34 +02:00
use parity_ethereum ::{ start , ExecutionAction } ;
2018-05-09 08:47:21 +02:00
use parking_lot ::{ Condvar , Mutex } ;
2016-12-10 23:58:39 +01:00
2016-12-11 03:33:10 +01:00
fn updates_path ( name : & str ) -> PathBuf {
2016-12-15 19:53:13 +01:00
let mut dest = PathBuf ::from ( default_hypervisor_path ( ) ) ;
2016-12-11 03:33:10 +01:00
dest . push ( name ) ;
2016-12-10 23:58:39 +01:00
dest
2016-09-06 15:31:13 +02:00
}
2016-12-11 03:33:10 +01:00
fn latest_exe_path ( ) -> Option < PathBuf > {
File ::open ( updates_path ( " latest " ) ) . ok ( )
. and_then ( | mut f | { let mut exe = String ::new ( ) ; f . read_to_string ( & mut exe ) . ok ( ) . map ( | _ | updates_path ( & exe ) ) } )
2016-12-22 18:26:39 +01:00
}
2016-12-11 03:33:10 +01:00
2017-03-13 12:10:53 +01:00
fn set_spec_name_override ( spec_name : String ) {
2017-03-23 13:25:31 +01:00
if let Err ( e ) = create_dir_all ( default_hypervisor_path ( ) )
2018-05-16 20:09:59 +02:00
. and_then ( | _ | File ::create ( updates_path ( " spec_name_override " ) )
2017-03-23 13:25:31 +01:00
. and_then ( | mut f | f . write_all ( spec_name . as_bytes ( ) ) ) )
2017-03-13 12:10:53 +01:00
{
2018-05-16 20:09:59 +02:00
warn! ( " Couldn't override chain spec: {} at {:?} " , e , updates_path ( " spec_name_override " ) ) ;
2017-03-13 12:10:53 +01:00
}
}
fn take_spec_name_override ( ) -> Option < String > {
2018-05-16 20:09:59 +02:00
let p = updates_path ( " spec_name_override " ) ;
2017-03-13 12:10:53 +01:00
let r = File ::open ( p . clone ( ) ) . ok ( )
. and_then ( | mut f | { let mut spec_name = String ::new ( ) ; f . read_to_string ( & mut spec_name ) . ok ( ) . map ( | _ | spec_name ) } ) ;
let _ = remove_file ( p ) ;
r
}
2017-01-17 23:34:46 +01:00
#[ cfg(windows) ]
fn global_cleanup ( ) {
2018-05-15 07:46:37 +02:00
// We need to cleanup all sockets before spawning another Parity process. This makes sure everything is cleaned up.
2018-04-21 12:54:48 +02:00
// The loop is required because of internal reference counter for winsock dll. We don't know how many crates we use do
2017-01-17 23:34:46 +01:00
// initialize it. There's at least 2 now.
for _ in 0 .. 10 {
2018-04-11 15:22:48 +02:00
unsafe { ::winapi ::um ::winsock2 ::WSACleanup ( ) ; }
2017-03-23 13:25:31 +01:00
}
}
#[ cfg(not(windows)) ]
fn global_init ( ) { }
#[ cfg(windows) ]
fn global_init ( ) {
// When restarting in the same process this reinits windows sockets.
unsafe {
const WS_VERSION : u16 = 0x202 ;
2018-04-11 15:22:48 +02:00
let mut wsdata : ::winapi ::um ::winsock2 ::WSADATA = ::std ::mem ::zeroed ( ) ;
::winapi ::um ::winsock2 ::WSAStartup ( WS_VERSION , & mut wsdata ) ;
2017-01-17 23:34:46 +01:00
}
}
#[ cfg(not(windows)) ]
fn global_cleanup ( ) { }
2016-12-10 23:58:39 +01:00
// Starts ~/.parity-updates/parity and returns the code it exits with.
fn run_parity ( ) -> Option < i32 > {
2017-03-23 13:25:31 +01:00
global_init ( ) ;
2016-12-11 04:05:02 +01:00
use ::std ::ffi ::OsString ;
let prefix = vec! [ OsString ::from ( " --can-restart " ) , OsString ::from ( " --force-direct " ) ] ;
2017-03-23 13:25:31 +01:00
let res = latest_exe_path ( ) . and_then ( | exe | process ::Command ::new ( exe )
2017-01-17 23:34:46 +01:00
. args ( & ( env ::args_os ( ) . skip ( 1 ) . chain ( prefix . into_iter ( ) ) . collect ::< Vec < _ > > ( ) ) )
2016-12-11 04:05:02 +01:00
. status ( )
. map ( | es | es . code ( ) . unwrap_or ( 128 ) )
. ok ( )
2017-03-23 13:25:31 +01:00
) ;
global_cleanup ( ) ;
res
2016-12-10 23:58:39 +01:00
}
const PLEASE_RESTART_EXIT_CODE : i32 = 69 ;
2018-07-02 11:53:50 +02:00
#[ derive(Debug) ]
/// Status used to exit or restart the program.
struct ExitStatus {
/// Whether the program panicked.
panicking : bool ,
/// Whether the program should exit.
should_exit : bool ,
/// Whether the program should restart.
should_restart : bool ,
/// If a restart happens, whether a new chain spec should be used.
spec_name_override : Option < String > ,
}
2016-12-10 23:58:39 +01:00
// Run our version of parity.
2016-12-22 18:26:39 +01:00
// Returns the exit error code.
2018-04-13 14:21:15 +02:00
fn main_direct ( force_can_restart : bool ) -> i32 {
2017-03-23 13:25:31 +01:00
global_init ( ) ;
2018-05-09 08:47:21 +02:00
let mut conf = {
let args = std ::env ::args ( ) . collect ::< Vec < _ > > ( ) ;
2018-07-05 15:27:34 +02:00
parity_ethereum ::Configuration ::parse_cli ( & args ) . unwrap_or_else ( | e | e . exit ( ) )
2018-05-09 08:47:21 +02:00
} ;
if let Some ( spec_override ) = take_spec_name_override ( ) {
conf . args . flag_testnet = false ;
conf . args . arg_chain = spec_override ;
}
let can_restart = force_can_restart | | conf . args . flag_can_restart ;
// increase max number of open files
raise_fd_limit ( ) ;
2018-07-02 11:53:50 +02:00
let exit = Arc ::new ( ( Mutex ::new ( ExitStatus {
panicking : false ,
should_exit : false ,
should_restart : false ,
spec_name_override : None
} ) , Condvar ::new ( ) ) ) ;
// Double panic can happen. So when we lock `ExitStatus` after the main thread is notified, it cannot be locked
// again.
let exiting = Arc ::new ( AtomicBool ::new ( false ) ) ;
2018-05-09 08:47:21 +02:00
let exec = if can_restart {
2018-07-02 11:53:50 +02:00
start (
conf ,
{
let e = exit . clone ( ) ;
let exiting = exiting . clone ( ) ;
move | new_chain : String | {
if ! exiting . swap ( true , Ordering ::SeqCst ) {
* e . 0. lock ( ) = ExitStatus {
panicking : false ,
should_exit : true ,
should_restart : true ,
spec_name_override : Some ( new_chain ) ,
} ;
e . 1. notify_all ( ) ;
}
}
} ,
{
let e = exit . clone ( ) ;
let exiting = exiting . clone ( ) ;
move | | {
if ! exiting . swap ( true , Ordering ::SeqCst ) {
* e . 0. lock ( ) = ExitStatus {
panicking : false ,
should_exit : true ,
should_restart : true ,
spec_name_override : None ,
} ;
e . 1. notify_all ( ) ;
}
}
}
)
2016-09-06 15:31:13 +02:00
} else {
2018-05-09 08:47:21 +02:00
trace! ( target : " mode " , " Not hypervised: not setting exit handlers. " ) ;
start ( conf , move | _ | { } , move | | { } )
} ;
let res = match exec {
Ok ( result ) = > match result {
ExecutionAction ::Instant ( Some ( s ) ) = > { println! ( " {} " , s ) ; 0 } ,
ExecutionAction ::Instant ( None ) = > 0 ,
ExecutionAction ::Running ( client ) = > {
2018-07-02 11:53:50 +02:00
panic_hook ::set_with ( {
let e = exit . clone ( ) ;
let exiting = exiting . clone ( ) ;
move | | {
if ! exiting . swap ( true , Ordering ::SeqCst ) {
* e . 0. lock ( ) = ExitStatus {
panicking : true ,
should_exit : true ,
should_restart : false ,
spec_name_override : None ,
} ;
e . 1. notify_all ( ) ;
}
}
} ) ;
2018-05-09 08:47:21 +02:00
CtrlC ::set_handler ( {
let e = exit . clone ( ) ;
2018-07-02 11:53:50 +02:00
let exiting = exiting . clone ( ) ;
move | | {
if ! exiting . swap ( true , Ordering ::SeqCst ) {
* e . 0. lock ( ) = ExitStatus {
panicking : false ,
should_exit : true ,
should_restart : false ,
spec_name_override : None ,
} ;
e . 1. notify_all ( ) ;
}
}
2018-05-09 08:47:21 +02:00
} ) ;
// Wait for signal
let mut lock = exit . 0. lock ( ) ;
2018-07-02 11:53:50 +02:00
if ! lock . should_exit {
let _ = exit . 1. wait ( & mut lock ) ;
}
2018-05-09 08:47:21 +02:00
client . shutdown ( ) ;
2018-07-02 11:53:50 +02:00
if lock . should_restart {
if let Some ( ref spec_name ) = lock . spec_name_override {
set_spec_name_override ( spec_name . clone ( ) ) ;
}
PLEASE_RESTART_EXIT_CODE
} else {
if lock . panicking {
1
} else {
0
}
2018-04-13 14:21:15 +02:00
}
2016-12-10 23:58:39 +01:00
} ,
2018-05-09 08:47:21 +02:00
} ,
Err ( err ) = > {
writeln! ( & mut stdio ::stderr ( ) , " {} " , err ) . expect ( " StdErr available; qed " ) ;
1
} ,
2017-03-23 13:25:31 +01:00
} ;
2018-05-09 08:47:21 +02:00
2017-03-23 13:25:31 +01:00
global_cleanup ( ) ;
res
2016-09-06 15:31:13 +02:00
}
2016-12-10 23:58:39 +01:00
fn println_trace_main ( s : String ) {
if env ::var ( " RUST_LOG " ) . ok ( ) . and_then ( | s | s . find ( " main=trace " ) ) . is_some ( ) {
println! ( " {} " , s ) ;
2016-07-26 00:21:08 +02:00
}
2016-12-10 23:58:39 +01:00
}
2016-07-26 00:21:08 +02:00
2016-12-10 23:58:39 +01:00
#[ macro_export ]
macro_rules ! trace_main {
( $arg :expr ) = > ( println_trace_main ( $arg . into ( ) ) ) ;
( $( $arg :tt ) * ) = > ( println_trace_main ( format! ( " {} " , format_args! ( $( $arg ) * ) ) ) ) ;
}
2016-08-24 18:35:38 +02:00
2016-12-10 23:58:39 +01:00
fn main ( ) {
2018-07-02 11:53:50 +02:00
panic_hook ::set_abort ( ) ;
2016-12-10 23:58:39 +01:00
// assuming the user is not running with `--force-direct`, then:
// if argv[0] == "parity" and this executable != ~/.parity-updates/parity, run that instead.
let force_direct = std ::env ::args ( ) . any ( | arg | arg = = " --force-direct " ) ;
let exe = std ::env ::current_exe ( ) . ok ( ) ;
2016-12-11 02:02:40 +01:00
let development = exe . as_ref ( ) . and_then ( | p | p . parent ( ) . and_then ( | p | p . parent ( ) ) . and_then ( | p | p . file_name ( ) ) . map ( | n | n = = " target " ) ) . unwrap_or ( false ) ;
2016-12-11 03:33:10 +01:00
let same_name = exe . as_ref ( ) . map ( | p | p . file_stem ( ) . map_or ( false , | s | s = = " parity " ) & & p . extension ( ) . map_or ( true , | x | x = = " exe " ) ) . unwrap_or ( false ) ;
2017-01-17 23:34:46 +01:00
trace_main! ( " Starting up {} (force-direct: {}, development: {}, same-name: {}) " , std ::env ::current_exe ( ) . map ( | x | format! ( " {} " , x . display ( ) ) ) . unwrap_or ( " <unknown> " . to_owned ( ) ) , force_direct , development , same_name ) ;
if ! force_direct & & ! development & & same_name {
2016-12-10 23:58:39 +01:00
// looks like we're not running ~/.parity-updates/parity when the user is expecting otherwise.
2016-12-22 18:26:39 +01:00
// Everything run inside a loop, so we'll be able to restart from the child into a new version seamlessly.
2016-12-10 23:58:39 +01:00
loop {
2016-12-22 18:26:39 +01:00
// If we fail to run the updated parity then fallback to local version.
2017-01-17 23:34:46 +01:00
let latest_exe = latest_exe_path ( ) ;
let have_update = latest_exe . as_ref ( ) . map_or ( false , | p | p . exists ( ) ) ;
let is_non_updated_current = exe . as_ref ( ) . map_or ( false , | exe | latest_exe . as_ref ( ) . map_or ( false , | lexe | exe . canonicalize ( ) . ok ( ) ! = lexe . canonicalize ( ) . ok ( ) ) ) ;
2017-03-11 14:45:50 +01:00
let update_is_newer = match (
latest_exe . as_ref ( )
. and_then ( | p | metadata ( p . as_path ( ) ) . ok ( ) )
. and_then ( | m | m . modified ( ) . ok ( ) ) ,
exe . as_ref ( )
. and_then ( | p | metadata ( p . as_path ( ) ) . ok ( ) )
. and_then ( | m | m . modified ( ) . ok ( ) )
) {
( Some ( latest_exe_time ) , Some ( this_exe_time ) ) if latest_exe_time > this_exe_time = > true ,
_ = > false ,
} ;
2017-03-13 12:10:53 +01:00
trace_main! ( " Starting... (have-update: {}, non-updated-current: {}, update-is-newer: {}) " , have_update , is_non_updated_current , update_is_newer ) ;
2017-03-11 14:45:50 +01:00
let exit_code = if have_update & & is_non_updated_current & & update_is_newer {
2017-01-17 23:34:46 +01:00
trace_main! ( " Attempting to run latest update ({})... " , latest_exe . as_ref ( ) . expect ( " guarded by have_update; latest_exe must exist for have_update; qed " ) . display ( ) ) ;
run_parity ( ) . unwrap_or_else ( | | { trace_main! ( " Falling back to local... " ) ; main_direct ( true ) } )
} else {
trace_main! ( " No latest update. Attempting to direct... " ) ;
main_direct ( true )
} ;
2016-12-10 23:58:39 +01:00
trace_main! ( " Latest exited with {} " , exit_code ) ;
if exit_code ! = PLEASE_RESTART_EXIT_CODE {
trace_main! ( " Quitting... " ) ;
process ::exit ( exit_code ) ;
}
trace_main! ( " Rerunning... " ) ;
2016-05-24 20:29:19 +02:00
}
2016-12-10 23:58:39 +01:00
} else {
trace_main! ( " Running direct " ) ;
// Otherwise, we're presumably running the version we want. Just run and fall-through.
2018-04-13 14:21:15 +02:00
process ::exit ( main_direct ( false ) ) ;
2016-05-24 20:29:19 +02:00
}
2016-06-07 17:21:19 +02:00
}