From 50600dce9570a63d509d76219d825f84c572b885 Mon Sep 17 00:00:00 2001 From: ZmnSCPxj jxPCSnmZ Date: Wed, 29 Jul 2020 16:56:42 +0800 Subject: [PATCH] lightningd/lightningd.c: Create API to exit lightningd with an exit code. --- lightningd/lightningd.c | 42 ++++++++++++++++++++++++++++++++--------- lightningd/lightningd.h | 10 ++++++++++ 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index fc8a80714..c7cbedd2b 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -281,6 +281,11 @@ static struct lightningd *new_lightningd(const tal_t *ctx) */ ld->rpc_filemode = 0600; + /*~ This is the exit code to use on exit. + * Set to NULL meaning we are not interested in exiting yet. + */ + ld->exit_code = NULL; + return ld; } @@ -752,6 +757,14 @@ static void hsm_ecdh_failed(enum status_failreason fail, fatal("hsm failure: %s", fmt); } +/*~ This signals to the mainloop that some part wants to cleanly exit now. */ +void lightningd_exit(struct lightningd *ld, int exit_code) +{ + ld->exit_code = tal(ld, int); + *ld->exit_code = exit_code; + io_break(ld); +} + int main(int argc, char *argv[]) { struct lightningd *ld; @@ -764,6 +777,8 @@ int main(int argc, char *argv[]) struct ext_key *bip32_base; struct rlimit nofile = {1024, 1024}; + int exit_code = 0; + /*~ Make sure that we limit ourselves to something reasonable. Modesty * is a virtue. */ setrlimit(RLIMIT_NOFILE, &nofile); @@ -1003,10 +1018,17 @@ int main(int argc, char *argv[]) assert(io_loop_ret == ld); ld->state = LD_STATE_SHUTDOWN; - /* Keep this fd around, to write final response at the end. */ - stop_fd = io_conn_fd(ld->stop_conn); - io_close_taken_fd(ld->stop_conn); - stop_response = tal_steal(NULL, ld->stop_response); + /* Were we exited via `lightningd_exit`? */ + if (ld->exit_code) { + exit_code = *ld->exit_code; + stop_fd = -1; + stop_response = NULL; + } else { + /* Keep this fd around, to write final response at the end. */ + stop_fd = io_conn_fd(ld->stop_conn); + io_close_taken_fd(ld->stop_conn); + stop_response = tal_steal(NULL, ld->stop_response); + } shutdown_subdaemons(ld); @@ -1041,11 +1063,13 @@ int main(int argc, char *argv[]) daemon_shutdown(); - /* Finally, send response to shutdown command */ - write_all(stop_fd, stop_response, strlen(stop_response)); - close(stop_fd); - tal_free(stop_response); + /* Finally, send response to shutdown command if appropriate. */ + if (stop_fd >= 0) { + write_all(stop_fd, stop_response, strlen(stop_response)); + close(stop_fd); + tal_free(stop_response); + } /*~ Farewell. Next stop: hsmd/hsmd.c. */ - return 0; + return exit_code; } diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index b5d7b3698..5ad15243e 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -271,6 +271,9 @@ struct lightningd { /* Total number of coin moves we've seen, since * coin move tracking was cool */ s64 coin_moves_count; + + /* If non-NULL, contains the exit code to use. */ + int *exit_code; }; /* Turning this on allows a tal allocation to return NULL, rather than aborting. @@ -289,4 +292,11 @@ void test_subdaemons(const struct lightningd *ld); /* Notify lightningd about new blocks. */ void notify_new_block(struct lightningd *ld, u32 block_height); +/* Signal a clean exit from lightningd. + * NOTE! This function **returns**. + * This just causes the main loop to exit, so you have to return + * all the way to the main loop for `lightningd` to exit. + */ +void lightningd_exit(struct lightningd *ld, int exit_code); + #endif /* LIGHTNING_LIGHTNINGD_LIGHTNINGD_H */