Skip to content
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

bin: handle TERM/INT signal #1058

Merged
merged 4 commits into from Sep 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 21 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -49,6 +49,7 @@ nix = "0.6.0"
utime = "0.1"
chrono = "0.2"
lazy_static = "0.2.1"
signal = "0.2"

# The getopts in crate.io is outdated, use the latest getopts instead.
[dependencies.getopts]
Expand Down
78 changes: 60 additions & 18 deletions src/bin/tikv-server.rs
Expand Up @@ -23,8 +23,12 @@ extern crate mio;
extern crate toml;
extern crate libc;
extern crate fs2;
#[cfg(unix)]
extern crate signal;
#[cfg(unix)]
extern crate nix;

use std::env;
use std::{env, thread};
use std::fs::{self, File};
use std::path::Path;
use std::sync::Arc;
Expand All @@ -34,6 +38,7 @@ use std::time::Duration;
use getopts::{Options, Matches};
use rocksdb::{Options as RocksdbOptions, BlockBasedOptions};
use mio::tcp::TcpListener;
use mio::EventLoop;
use fs2::FileExt;

use tikv::storage::{Storage, TEMP_DIR, ALL_CFS};
Expand All @@ -42,7 +47,8 @@ use tikv::util::transport::SendCh;
use tikv::server::{DEFAULT_LISTENING_ADDR, Server, Node, Config, bind, create_event_loop,
create_raft_storage, Msg};
use tikv::server::{ServerTransport, ServerRaftStoreRouter, MockRaftStoreRouter};
use tikv::server::{MockStoreAddrResolver, PdStoreAddrResolver};
use tikv::server::transport::RaftStoreRouter;
use tikv::server::{MockStoreAddrResolver, PdStoreAddrResolver, StoreAddrResolver};
use tikv::raftstore::store::{self, SnapManager};
use tikv::pd::RpcClient;
use tikv::util::time_monitor::TimeMonitor;
Expand Down Expand Up @@ -589,6 +595,42 @@ fn get_store_path(matches: &Matches, config: &toml::Value) -> String {
format!("{}", absolute_path.display())
}

fn start_server<T, S>(mut server: Server<T, S>, mut el: EventLoop<Server<T, S>>)
where T: RaftStoreRouter,
S: StoreAddrResolver + Send + 'static
{
let ch = server.get_sendch();
let h = thread::Builder::new()
.name("tikv-server".to_owned())
.spawn(move || {
server.run(&mut el).unwrap();
})
.unwrap();
handle_signal(ch);
h.join().unwrap();
}

#[cfg(unix)]
fn handle_signal(ch: SendCh<Msg>) {
use signal::trap::Trap;
use nix::sys::signal::{SIGTERM, SIGINT};
let trap = Trap::trap(&[SIGTERM, SIGINT]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will block until receiving a signal?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the for loop below will block.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't find any doc or example how trap should be used.
Will it rerun this piece of signal catching code if the specified signal happens? Like a callback.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for sig in trap {
match sig {
SIGTERM | SIGINT => {
info!("receive signal {}, stopping server...", sig);
ch.send(Msg::Quit).unwrap();
break;
}
// TODO: handle more signal
_ => unreachable!(),
}
}
}

#[cfg(not(unix))]
fn handle_signal(ch: SendCh<Msg>) {}

fn run_local_server(listener: TcpListener, config: &Config) {
let mut event_loop = create_event_loop(config).unwrap();
let snap_mgr = store::new_snap_mgr(TEMP_DIR, None);
Expand All @@ -598,15 +640,15 @@ fn run_local_server(listener: TcpListener, config: &Config) {
panic!("failed to start storage, error = {:?}", e);
}

let mut svr = Server::new(&mut event_loop,
config,
listener,
store,
MockRaftStoreRouter,
MockStoreAddrResolver,
snap_mgr)
let svr = Server::new(&mut event_loop,
config,
listener,
store,
MockRaftStoreRouter,
MockStoreAddrResolver,
snap_mgr)
.unwrap();
svr.run(&mut event_loop).unwrap();
start_server(svr, event_loop);
}

fn run_raft_server(listener: TcpListener, matches: &Matches, config: &toml::Value, cfg: &Config) {
Expand Down Expand Up @@ -638,15 +680,15 @@ fn run_raft_server(listener: TcpListener, matches: &Matches, config: &toml::Valu
panic!("failed to start storage, error = {:?}", e);
}

let mut svr = Server::new(&mut event_loop,
cfg,
listener,
store,
raft_router,
resolver,
snap_mgr)
let svr = Server::new(&mut event_loop,
cfg,
listener,
store,
raft_router,
resolver,
snap_mgr)
.unwrap();
svr.run(&mut event_loop).unwrap();
start_server(svr, event_loop);
node.stop().unwrap();
}

Expand Down