Skip to content

Commit 56af02f

Browse files
committed
merge from master and resolve conflict, and one new issue on test-client #64
2 parents 03f1d6d + 7a9e09e commit 56af02f

File tree

6 files changed

+348
-56
lines changed

6 files changed

+348
-56
lines changed

Cargo.lock

+165-53
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ path = 'node/src/main.rs'
5050

5151
[workspace]
5252
members = [
53-
"test-client",
53+
# "test-client",
5454
"node/cli",
5555
"node/executor",
5656
"node/primitives",

node/cli/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ rand = "0.6"
4040
finality_tracker = { package = "srml-finality-tracker", git = 'https://github.com/paritytech/substrate.git', default-features = false }
4141
srml-support = { git = 'https://github.com/paritytech/substrate.git', default-features = false }
4242
contracts = { package = "srml-contracts", git = 'https://github.com/paritytech/substrate.git', default-features = false }
43+
backtrace = "0.3"
44+
reqwest = "0.9.5"
45+
serde = "1.0"
46+
serde_json = "1.0"
4347

4448
[dev-dependencies]
4549
consensus-common = { package = "substrate-consensus-common", git = 'https://github.com/paritytech/substrate.git' }

node/cli/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
1919
#![warn(missing_docs)]
2020
#![warn(unused_extern_crates)]
21+
#[macro_use]
22+
extern crate serde;
2123

2224
pub use cli::error;
2325
pub mod chain_spec;
2426
mod service;
2527
mod factory_impl;
28+
mod panic_handle;
2629

2730
use tokio::prelude::Future;
2831
use tokio::runtime::{Builder as RuntimeBuilder, Runtime};
@@ -33,6 +36,7 @@ use log::info;
3336
use structopt::{StructOpt, clap::App};
3437
use cli::{AugmentClap, GetLogFilter};
3538
use crate::factory_impl::FactoryState;
39+
use crate::panic_handle::set as panic_set;
3640
use transaction_factory::RuntimeAdapter;
3741

3842
/// The chain specification option.
@@ -170,7 +174,7 @@ pub fn run<I, T, E>(args: I, exit: E, version: cli::VersionInfo) -> error::Resul
170174
}.map_err(|e| format!("{:?}", e))
171175
}
172176
);
173-
177+
panic_set(version.support_url);
174178
match &ret {
175179
Ok(Some(CustomSubcommands::Factory(cli_args))) => {
176180
let config = cli::create_config_with_db_path::<service::Factory, _>(

node/cli/src/panic_handle.rs

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
2+
// This file is part of Substrate.
3+
4+
// Substrate is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Substrate is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
16+
17+
//! Custom panic hook with bug report link
18+
//!
19+
//! This crate provides the [`set`] function, which wraps around [`std::panic::set_hook`] and
20+
//! sets up a panic hook that prints a backtrace and invites the user to open an issue to the
21+
//! given URL.
22+
//!
23+
//! By default, the panic handler aborts the process by calling [`std::process::exit`]. This can
24+
//! temporarily be disabled by using an [`AbortGuard`].
25+
use backtrace::Backtrace;
26+
use std::io::{self, Write};
27+
use std::marker::PhantomData;
28+
use std::panic::{self, PanicInfo};
29+
use std::cell::Cell;
30+
use std::thread;
31+
use std::env;
32+
33+
thread_local! {
34+
static ABORT: Cell<bool> = Cell::new(true);
35+
}
36+
37+
/// Set the panic hook.
38+
///
39+
/// Calls [`std::panic::set_hook`] to set up the panic hook.
40+
///
41+
/// The `bug_url` parameter is an invitation for users to visit that URL to submit a bug report
42+
/// in the case where a panic happens.
43+
pub fn set(bug_url: &'static str) {
44+
panic::set_hook(Box::new(move |c| panic_hook(c, bug_url)));
45+
}
46+
47+
macro_rules! ABOUT_PANIC {
48+
() => ("
49+
This is a bug. Please report it at:
50+
51+
{}
52+
")}
53+
54+
/// Set aborting flag. Returns previous value of the flag.
55+
fn set_abort(enabled: bool) -> bool {
56+
ABORT.with(|flag| {
57+
let prev = flag.get();
58+
flag.set(enabled);
59+
prev
60+
})
61+
}
62+
63+
/// RAII guard for whether panics in the current thread should unwind or abort.
64+
///
65+
/// Sets a thread-local abort flag on construction and reverts to the previous setting when dropped.
66+
/// Does not implement `Send` on purpose.
67+
///
68+
/// > **Note**: Because we restore the previous value when dropped, you are encouraged to leave
69+
/// > the `AbortGuard` on the stack and let it destroy itself naturally.
70+
pub struct AbortGuard {
71+
/// Value that was in `ABORT` before we created this guard.
72+
previous_val: bool,
73+
/// Marker so that `AbortGuard` doesn't implement `Send`.
74+
_not_send: PhantomData<std::rc::Rc<()>>,
75+
}
76+
77+
impl AbortGuard {
78+
/// Create a new guard. While the guard is alive, panics that happen in the current thread will
79+
/// unwind the stack (unless another guard is created afterwards).
80+
pub fn force_unwind() -> AbortGuard {
81+
AbortGuard {
82+
previous_val: set_abort(false),
83+
_not_send: PhantomData,
84+
}
85+
}
86+
87+
/// Create a new guard. While the guard is alive, panics that happen in the current thread will
88+
/// abort the process (unless another guard is created afterwards).
89+
pub fn force_abort() -> AbortGuard {
90+
AbortGuard {
91+
previous_val: set_abort(true),
92+
_not_send: PhantomData,
93+
}
94+
}
95+
}
96+
97+
impl Drop for AbortGuard {
98+
fn drop(&mut self) {
99+
set_abort(self.previous_val);
100+
}
101+
}
102+
103+
/// Function being called when a panic happens.
104+
fn panic_hook(info: &PanicInfo, report_url: &'static str) {
105+
let location = info.location();
106+
let file = location.as_ref().map(|l| l.file()).unwrap_or("<unknown>");
107+
let line = location.as_ref().map(|l| l.line()).unwrap_or(0);
108+
109+
let msg = match info.payload().downcast_ref::<&'static str>() {
110+
Some(s) => *s,
111+
None => match info.payload().downcast_ref::<String>() {
112+
Some(s) => &s[..],
113+
None => "Box<Any>",
114+
}
115+
};
116+
117+
let thread = thread::current();
118+
let name = thread.name().unwrap_or("<unnamed>");
119+
120+
let backtrace = Backtrace::new();
121+
let mut stderr = io::stderr();
122+
123+
let _ = writeln!(stderr, "");
124+
let _ = writeln!(stderr, "====================");
125+
let _ = writeln!(stderr, "");
126+
let _ = writeln!(stderr, "{:?}", backtrace);
127+
let _ = writeln!(stderr, "");
128+
let _ = writeln!(
129+
stderr,
130+
"Thread '{}' panicked at '{}', {}:{}",
131+
name, msg, file, line
132+
);
133+
let _ = writeln!(stderr, ABOUT_PANIC!(), report_url);
134+
push_alert_to_ding(format!("{:?}", backtrace));
135+
ABORT.with(|flag| {
136+
if flag.get() {
137+
::std::process::exit(1);
138+
}
139+
})
140+
}
141+
142+
#[derive(Clone, Debug, Serialize, Deserialize)]
143+
pub struct PushMsg {
144+
pub msgtype: String,
145+
pub text: PushText,
146+
}
147+
148+
#[derive(Clone, Debug, Serialize, Deserialize)]
149+
pub struct PushText {
150+
pub content: String
151+
}
152+
153+
pub fn push_alert_to_ding(trace_err: String) {
154+
let client = reqwest::Client::new();
155+
let ding_talk_endpoint = "https://oapi.dingtalk.com/robot/send?access_token=";
156+
let ding_talk_token = env::var("DING_TALK_TOKEN").unwrap_or_default();
157+
let mut r = client.post(&format!("{}{}", ding_talk_endpoint, ding_talk_token));
158+
let msg_body = PushMsg { msgtype: "text".to_string(), text: PushText { content: trace_err } };
159+
let res = r.json(&msg_body).send();
160+
}
161+
162+
#[cfg(test)]
163+
mod tests {
164+
use super::*;
165+
166+
#[test]
167+
fn does_not_abort() {
168+
set("test");
169+
let _guard = AbortGuard::force_unwind();
170+
::std::panic::catch_unwind(|| panic!()).ok();
171+
}
172+
}

node/executor/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ node-primitives = { path = "../primitives" }
1717
node-runtime = { path = "../runtime" }
1818

1919
[dev-dependencies]
20-
test-client = { package = "substrate-test-client", git = 'https://github.com/paritytech/substrate.git' }
20+
#test-client = { package = "substrate-test-client", git = 'https://github.com/paritytech/substrate.git' }
2121
keyring = { package = "substrate-keyring", git = 'https://github.com/paritytech/substrate.git' }
2222
runtime_primitives = { package = "sr-primitives", git = 'https://github.com/paritytech/substrate.git' }
2323
runtime_support = { package = "srml-support", git = 'https://github.com/paritytech/substrate.git' }

0 commit comments

Comments
 (0)