From 2273ce783ef1291da2ec79a701929d80795a1291 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 11 Oct 2017 20:39:49 +1030 Subject: [PATCH] dev_disconnect: support multiple disconnects in the same daemon. We currently assume the daemon gives up; gossipd won't, and we want to test it there too. This reveals a bug (returning io_close() is bad if the call is to duplex()), and breaks a test which now continues after dropping a packet.. Signed-off-by: Rusty Russell --- common/cryptomsg.c | 3 ++- common/dev_disconnect.c | 20 ++++++++++++++------ tests/test_lightningd.py | 7 +++++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/common/cryptomsg.c b/common/cryptomsg.c index b23af5b4a..f3f18e717 100644 --- a/common/cryptomsg.c +++ b/common/cryptomsg.c @@ -346,7 +346,8 @@ struct io_plan *peer_write_message(struct io_conn *conn, switch (dev_disconnect(type)) { case DEV_DISCONNECT_BEFORE: - return io_close(conn); + dev_sabotage_fd(io_conn_fd(conn)); + break; case DEV_DISCONNECT_DROPPKT: pcs->out = NULL; /* FALL THRU */ case DEV_DISCONNECT_AFTER: diff --git a/common/dev_disconnect.c b/common/dev_disconnect.c index 3c2ecefe2..ae0e15961 100644 --- a/common/dev_disconnect.c +++ b/common/dev_disconnect.c @@ -19,15 +19,16 @@ static bool dev_disconnect_nocommit; bool dev_suppress_commit; -void dev_disconnect_init(int fd) +static void next_dev_disconnect(void) { int r; char *asterisk; - r = read(fd, dev_disconnect_line, sizeof(dev_disconnect_line)-1); + r = read(dev_disconnect_fd, + dev_disconnect_line, sizeof(dev_disconnect_line)-1); if (r < 0) err(1, "Reading dev_disconnect file"); - lseek(fd, -r, SEEK_CUR); + lseek(dev_disconnect_fd, -r, SEEK_CUR); /* Get first line */ dev_disconnect_line[r] = '\n'; @@ -49,22 +50,29 @@ void dev_disconnect_init(int fd) *asterisk = '\0'; } else dev_disconnect_count = 1; +} +void dev_disconnect_init(int fd) +{ /* So we can move forward if we do use the line. */ dev_disconnect_fd = fd; } enum dev_disconnect dev_disconnect(int pkt_type) { + if (dev_disconnect_fd == -1) + return DEV_DISCONNECT_NORMAL; + + if (!dev_disconnect_count) + next_dev_disconnect(); + if (!streq(wire_type_name(pkt_type), dev_disconnect_line+1)) return DEV_DISCONNECT_NORMAL; - if (dev_disconnect_count != 1) { - dev_disconnect_count--; + if (--dev_disconnect_count != 0) { return DEV_DISCONNECT_NORMAL; } - assert(dev_disconnect_fd != -1); lseek(dev_disconnect_fd, dev_disconnect_len+1, SEEK_CUR); status_trace("dev_disconnect: %s%s", dev_disconnect_line, diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 850510214..c095b9c07 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -1354,9 +1354,12 @@ class LightningDTests(BaseLightningDTests): assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True def test_reconnect_receiver_fulfill(self): - disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', - '@WIRE_UPDATE_FULFILL_HTLC', + # Ordering matters: after +WIRE_UPDATE_FULFILL_HTLC, channeld + # will continue and try to send WIRE_COMMITMENT_SIGNED: if + # that's the next failure, it will do two in one run. + disconnects = ['@WIRE_UPDATE_FULFILL_HTLC', '+WIRE_UPDATE_FULFILL_HTLC', + '-WIRE_UPDATE_FULFILL_HTLC', '-WIRE_COMMITMENT_SIGNED', '@WIRE_COMMITMENT_SIGNED', '+WIRE_COMMITMENT_SIGNED',