From d4618fa1990f810e152a1c81756dee459b83c67a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 6 Jun 2017 12:38:42 +0930 Subject: [PATCH] subdaemons: handle master or gossipd failing. We should simply exit in this case. Signed-off-by: Rusty Russell --- lightningd/channel/channel.c | 16 ++++++++++++++-- lightningd/daemon_conn.c | 9 +++++++-- lightningd/daemon_conn.h | 4 +++- lightningd/gossip/gossip.c | 11 +++++++++-- lightningd/hsm/hsm.c | 11 +++++++++-- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index 3d9d2d8af..8c1581d71 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -1356,6 +1356,18 @@ out: } #ifndef TESTING +static void master_gone(struct io_conn *unused, struct daemon_conn *dc) +{ + /* Can't tell master, it's gone. */ + exit(2); +} + +static void gossip_gone(struct io_conn *unused, struct daemon_conn *dc) +{ + status_failed(WIRE_CHANNEL_GOSSIP_BAD_MESSAGE, + "Gossip connection closed"); +} + int main(int argc, char *argv[]) { struct peer *peer = tal(NULL, struct peer); @@ -1373,7 +1385,7 @@ int main(int argc, char *argv[]) secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - daemon_conn_init(peer, &peer->master, REQ_FD, req_in); + daemon_conn_init(peer, &peer->master, REQ_FD, req_in, master_gone); peer->channel = NULL; peer->htlc_id = 0; peer->num_pings_outstanding = 0; @@ -1397,7 +1409,7 @@ int main(int argc, char *argv[]) msg_queue_init(&peer->peer_out, peer); daemon_conn_init(peer, &peer->gossip_client, GOSSIP_FD, - gossip_client_recv); + gossip_client_recv, gossip_gone); init_peer_crypto_state(peer, &peer->pcs); peer->funding_locked[LOCAL] = peer->funding_locked[REMOTE] = false; diff --git a/lightningd/daemon_conn.c b/lightningd/daemon_conn.c index 8ab81ed49..d9f417126 100644 --- a/lightningd/daemon_conn.c +++ b/lightningd/daemon_conn.c @@ -62,15 +62,20 @@ static struct io_plan *daemon_conn_start(struct io_conn *conn, void daemon_conn_init(tal_t *ctx, struct daemon_conn *dc, int fd, struct io_plan *(*daemon_conn_recv)(struct io_conn *, - struct daemon_conn *)) + struct daemon_conn *), + void (*finish)(struct io_conn *, struct daemon_conn *dc)) { + struct io_conn *conn; + dc->daemon_conn_recv = daemon_conn_recv; dc->ctx = ctx; dc->msg_in = NULL; msg_queue_init(&dc->out, dc->ctx); dc->msg_queue_cleared_cb = NULL; - io_new_conn(ctx, fd, daemon_conn_start, dc); + conn = io_new_conn(ctx, fd, daemon_conn_start, dc); + if (finish) + io_set_finish(conn, finish, dc); } void daemon_conn_send(struct daemon_conn *dc, const u8 *msg) diff --git a/lightningd/daemon_conn.h b/lightningd/daemon_conn.h index bcc277bc3..ebf46f800 100644 --- a/lightningd/daemon_conn.h +++ b/lightningd/daemon_conn.h @@ -37,10 +37,12 @@ struct daemon_conn { * @dc: daemon_conn to initialize * @fd: socket file descriptor to wrap * @daemon_conn_recv: callback function to be called upon receiving a message + * @finish: finish function if connection is closed (can be NULL) */ void daemon_conn_init(tal_t *ctx, struct daemon_conn *dc, int fd, struct io_plan *(*daemon_conn_recv)( - struct io_conn *, struct daemon_conn *)); + struct io_conn *, struct daemon_conn *), + void (*finish)(struct io_conn *, struct daemon_conn *)); /** * daemon_conn_send - Enqueue an outgoing message to be sent */ diff --git a/lightningd/gossip/gossip.c b/lightningd/gossip/gossip.c index 44c83cc09..1ff51484d 100644 --- a/lightningd/gossip/gossip.c +++ b/lightningd/gossip/gossip.c @@ -145,7 +145,7 @@ static void send_peer_with_fds(struct peer *peer, const u8 *msg) /* Now we talk to socket to get to peer's owner daemon. */ peer->local = false; /* FIXME: Forget peer if other end is closed. */ - daemon_conn_init(peer, &peer->owner_conn, fds[0], owner_msg_in); + daemon_conn_init(peer, &peer->owner_conn, fds[0], owner_msg_in, NULL); peer->owner_conn.msg_queue_cleared_cb = nonlocal_dump_gossip; /* Peer stays around, even though we're going to free conn. */ @@ -700,6 +700,12 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master } #ifndef TESTING +static void master_gone(struct io_conn *unused, struct daemon_conn *dc) +{ + /* Can't tell master, it's gone. */ + exit(2); +} + int main(int argc, char *argv[]) { struct daemon *daemon; @@ -728,7 +734,8 @@ int main(int argc, char *argv[]) daemon->broadcast_interval = 30000; /* stdin == control */ - daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req); + daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req, + master_gone); status_setup_async(&daemon->master); /* When conn closes, everything is freed. */ diff --git a/lightningd/hsm/hsm.c b/lightningd/hsm/hsm.c index 1af139347..01e5f9e85 100644 --- a/lightningd/hsm/hsm.c +++ b/lightningd/hsm/hsm.c @@ -82,7 +82,7 @@ static struct client *new_client(struct daemon_conn *master, c->id = id; c->handle = handle; c->master = master; - daemon_conn_init(c, &c->dc, fd, handle); + daemon_conn_init(c, &c->dc, fd, handle, NULL); /* Free the connection if we exit everything. */ tal_steal(master, c->dc.conn); @@ -586,6 +586,12 @@ static struct io_plan *control_received_req(struct io_conn *conn, } #ifndef TESTING +static void master_gone(struct io_conn *unused, struct daemon_conn *dc) +{ + /* Can't tell master, it's gone. */ + exit(2); +} + int main(int argc, char *argv[]) { struct daemon_conn *master; @@ -600,7 +606,8 @@ int main(int argc, char *argv[]) | SECP256K1_CONTEXT_SIGN); master = tal(NULL, struct daemon_conn); - daemon_conn_init(master, master, STDIN_FILENO, control_received_req); + daemon_conn_init(master, master, STDIN_FILENO, control_received_req, + master_gone); status_setup_async(master); /* When conn closes, everything is freed. */