diff --git a/lightningd/channel/channel.c b/lightningd/channel/channel.c index 094fe9c0d..763c31cb3 100644 --- a/lightningd/channel/channel.c +++ b/lightningd/channel/channel.c @@ -312,7 +312,7 @@ int main(int argc, char *argv[]) daemon_conn_init(peer, &peer->master, REQ_FD, req_in); peer->channel = NULL; - status_setup(REQ_FD); + status_setup_async(&peer->master); msg_queue_init(&peer->peer_out, peer); daemon_conn_init(peer, &peer->gossip_client, GOSSIP_FD, diff --git a/lightningd/connection.c b/lightningd/connection.c index 978bc5b9e..9366108d1 100644 --- a/lightningd/connection.c +++ b/lightningd/connection.c @@ -1,7 +1,9 @@ #include "connection.h" +#include #include #include #include +#include struct io_plan *daemon_conn_read_next(struct io_conn *conn, struct daemon_conn *dc) @@ -30,6 +32,26 @@ struct io_plan *daemon_conn_write_next(struct io_conn *conn, } } +bool daemon_conn_sync_flush(struct daemon_conn *dc) +{ + const u8 *msg; + + /* Flush any current packet. */ + if (!io_flush_sync(dc->conn)) + return false; + + /* Flush existing messages. */ + while ((msg = msg_dequeue(&dc->out)) != NULL) { + int fd = msg_is_fd(msg); + if (fd >= 0) { + if (!fdpass_send(io_conn_fd(dc->conn), fd)) + return false; + } else if (!wire_sync_write(io_conn_fd(dc->conn), msg)) + return false; + } + return true; +} + static struct io_plan *daemon_conn_start(struct io_conn *conn, struct daemon_conn *dc) { diff --git a/lightningd/connection.h b/lightningd/connection.h index 9694e23fb..e40ec45a5 100644 --- a/lightningd/connection.h +++ b/lightningd/connection.h @@ -66,4 +66,8 @@ struct io_plan *daemon_conn_write_next(struct io_conn *conn, struct io_plan *daemon_conn_read_next(struct io_conn *conn, struct daemon_conn *dc); +/** + * daemon_conn_sync_flush - Flush connection by sending all messages now.. + */ +bool daemon_conn_sync_flush(struct daemon_conn *dc); #endif /* LIGHTNING_LIGHTNINGD_CONNECTION_H */ diff --git a/lightningd/gossip/gossip.c b/lightningd/gossip/gossip.c index 725c3585e..ccd26069a 100644 --- a/lightningd/gossip/gossip.c +++ b/lightningd/gossip/gossip.c @@ -537,8 +537,8 @@ int main(int argc, char *argv[]) timers_init(&daemon->timers, time_mono()); /* stdin == control */ - status_setup(STDIN_FILENO); daemon_conn_init(daemon, &daemon->master, STDIN_FILENO, recv_req); + status_setup_async(&daemon->master); for (;;) { struct timer *expired = NULL; io_loop(&daemon->timers, &expired); diff --git a/lightningd/handshake/handshake.c b/lightningd/handshake/handshake.c index 116eba902..f3c5aaf74 100644 --- a/lightningd/handshake/handshake.c +++ b/lightningd/handshake/handshake.c @@ -308,7 +308,7 @@ static void act_one_initiator(struct handshake *h, int fd, struct act_one act1; size_t len; - status_send(towire_initr_act_one(h)); + status_send_sync(towire_initr_act_one(h)); /* BOLT #8: * @@ -390,7 +390,7 @@ static void act_one_responder(struct handshake *h, int fd, struct pubkey *re) { struct act_one act1; - status_send(towire_respr_act_one(h)); + status_send_sync(towire_respr_act_one(h)); /* BOLT #8: * @@ -519,7 +519,7 @@ static void act_two_responder(struct handshake *h, int fd, struct act_two act2; size_t len; - status_send(towire_respr_act_two(h)); + status_send_sync(towire_respr_act_two(h)); /* BOLT #8: * @@ -602,7 +602,7 @@ static void act_two_initiator(struct handshake *h, int fd, struct pubkey *re) { struct act_two act2; - status_send(towire_initr_act_two(h)); + status_send_sync(towire_initr_act_two(h)); /* BOLT #8: * @@ -731,7 +731,7 @@ static void act_three_initiator(struct handshake *h, int fd, u8 spub[PUBKEY_DER_LEN]; size_t len = sizeof(spub); - status_send(towire_initr_act_three(h)); + status_send_sync(towire_initr_act_three(h)); /* BOLT #8: * * `c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed())` @@ -803,7 +803,7 @@ static void act_three_responder(struct handshake *h, int fd, struct act_three act3; u8 der[PUBKEY_DER_LEN]; - status_send(towire_respr_act_three(h)); + status_send_sync(towire_respr_act_three(h)); /* BOLT #8: * @@ -979,7 +979,7 @@ int main(int argc, char *argv[]) subdaemon_debug(argc, argv); secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - status_setup(REQ_FD); + status_setup_sync(REQ_FD); hsm_setup(hsmfd); diff --git a/lightningd/handshake/test/run-handshake.c b/lightningd/handshake/test/run-handshake.c index b43b8d1a0..81eef856b 100644 --- a/lightningd/handshake/test/run-handshake.c +++ b/lightningd/handshake/test/run-handshake.c @@ -25,7 +25,7 @@ static ssize_t fake_write_all(int fd, const void *buf, size_t count) static const char *status_prefix; /* Simply print out status updates. */ -#define status_send(msg) \ +#define status_send_sync(msg) \ printf("%s:# Act %s\n", status_prefix, \ fromwire_peektype(msg) == WIRE_INITR_ACT_ONE ? "One" \ : fromwire_peektype(msg) == WIRE_INITR_ACT_TWO ? "Two" \ diff --git a/lightningd/hsm/hsm.c b/lightningd/hsm/hsm.c index eebb79112..ad18d14ab 100644 --- a/lightningd/hsm/hsm.c +++ b/lightningd/hsm/hsm.c @@ -426,7 +426,7 @@ int main(int argc, char *argv[]) master = tal(NULL, struct daemon_conn); daemon_conn_init(master, master, STDIN_FILENO, control_received_req); - status_setup(STDIN_FILENO); + status_setup_async(master); /* When conn closes, everything is freed. */ tal_steal(master->conn, master); diff --git a/lightningd/opening/opening.c b/lightningd/opening/opening.c index c399a8f29..fa3c98d0a 100644 --- a/lightningd/opening/opening.c +++ b/lightningd/opening/opening.c @@ -676,7 +676,7 @@ int main(int argc, char *argv[]) signal(SIGCHLD, SIG_IGN); secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - status_setup(REQ_FD); + status_setup_sync(REQ_FD); msg = wire_sync_read(state, REQ_FD); if (!msg) diff --git a/lightningd/status.c b/lightningd/status.c index 8fa0ec98c..e7c0967c8 100644 --- a/lightningd/status.c +++ b/lightningd/status.c @@ -1,4 +1,3 @@ -#include "status.h" #include "utils.h" #include "wire/wire.h" #include "wire/wire_sync.h" @@ -8,18 +7,32 @@ #include #include #include +#include #include +#include +#include #include static int status_fd = -1; +static struct daemon_conn *status_conn; const void *trc; -void status_setup(int fd) +void status_setup_sync(int fd) { + assert(status_fd == -1); + assert(!status_conn); status_fd = fd; trc = tal_tmpctx(NULL); } +void status_setup_async(struct daemon_conn *master) +{ + assert(status_fd == -1); + assert(!status_conn); + status_conn = master; + trc = tal_tmpctx(NULL); +} + static bool too_large(size_t len, int type) { if (len > 65535) { @@ -30,7 +43,7 @@ static bool too_large(size_t len, int type) return false; } -void status_send(const u8 *p) +void status_send_sync(const u8 *p) { const u8 *msg = p; assert(status_fd >= 0); @@ -43,16 +56,6 @@ void status_send(const u8 *p) tal_free(p); } -void status_send_fd(int fd) -{ - assert(status_fd >= 0); - assert(fd >= 0); - - if (!fdpass_send(status_fd, fd)) - err(1, "Writing out status fd %i", fd); - close(fd); -} - static void status_send_with_hdr(u16 type, const void *p, size_t len) { be16 be_type, be_len; @@ -62,13 +65,19 @@ static void status_send_with_hdr(u16 type, const void *p, size_t len) be_type = cpu_to_be16(type); be_len = cpu_to_be16(len + sizeof(be_type)); - assert(status_fd >= 0); assert(be16_to_cpu(be_len) == len + sizeof(be_type)); - if (!write_all(status_fd, &be_len, sizeof(be_len)) - || !write_all(status_fd, &be_type, sizeof(be_type)) - || !write_all(status_fd, p, len)) - err(1, "Writing out status %u len %zu", type, len); + if (status_fd >= 0) { + if (!write_all(status_fd, &be_len, sizeof(be_len)) + || !write_all(status_fd, &be_type, sizeof(be_type)) + || !write_all(status_fd, p, len)) + err(1, "Writing out status %u len %zu", type, len); + } else { + u8 *msg = tal_arr(NULL, u8, sizeof(be_type) + len); + memcpy(msg, &be_type, sizeof(be_type)); + memcpy(msg + sizeof(be_type), p, len); + daemon_conn_send(status_conn, take(msg)); + } } void status_trace(const char *fmt, ...) @@ -99,5 +108,10 @@ void status_failed(u16 code, const char *fmt, ...) status_send_with_hdr(code, str, strlen(str)); va_end(ap); + /* Don't let it take forever. */ + alarm(10); + if (status_conn) + daemon_conn_sync_flush(status_conn); + exit(0x80 | (code & 0xFF)); } diff --git a/lightningd/status.h b/lightningd/status.h index 8256a4b97..07c7dc107 100644 --- a/lightningd/status.h +++ b/lightningd/status.h @@ -5,8 +5,11 @@ #include #include +struct daemon_conn; + /* Simple status reporting API. */ -void status_setup(int fd); +void status_setup_sync(int fd); +void status_setup_async(struct daemon_conn *master); /* Convenient context, frees up after every status_update/failed */ extern const void *trc; @@ -18,9 +21,7 @@ extern const void *trc; #define STATUS_FAIL 0x8000 /* Send a message (frees the message). */ -void status_send(const u8 *msg); -/* Send a file descriptor (closes fd). */ -void status_send_fd(int fd); +void status_send_sync(const u8 *msg); /* Send a printf-style debugging trace. */ void status_trace(const char *fmt, ...) PRINTF_FMT(1,2); /* Send a failure status code with printf-style msg, and exit. */