Skip to content

Commit 2146a54

Browse files
committed
plugin: Do not return multiple times from pay
While we were unsetting the `payment->cmd` in case of a success to signal that we should not return to the JSON-RPC command twice, we were not doing that in the case of failures. This was causing multiple responses to a single incoming command, and `lightningd` was correctly killing the plugin. This issue was introduced through early returns (anything setting `payment->abort=true`) and was caused in Rusty's case through an MPP timeout. Fixes #3847 Reported-by: Rusty Russell <@rustyrussell> Signed-off-by: Christian Decker <@cdecker>
1 parent 734f292 commit 2146a54

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

plugins/libplugin-pay.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,18 +1063,20 @@ static void payment_finished(struct payment *p)
10631063
assert((result.leafstates & PAYMENT_STEP_SUCCESS) == 0 ||
10641064
result.preimage != NULL);
10651065

1066-
if (p->parent == NULL && cmd == NULL) {
1067-
/* This is the tree root, but we already reported success or
1068-
* failure, so noop. */
1069-
return;
1070-
1071-
} else if (p->parent == NULL) {
1072-
if (payment_is_success(p)) {
1066+
if (p->parent == NULL) {
1067+
/* We are about to reply, unset the pointer to the cmd so we
1068+
* don't attempt to return a response twice. */
1069+
p->cmd = NULL;
1070+
if (cmd == NULL) {
1071+
/* This is the tree root, but we already reported
1072+
* success or failure, so noop. */
1073+
return;
1074+
} else if (payment_is_success(p)) {
10731075
assert(result.treestates & PAYMENT_STEP_SUCCESS);
10741076
assert(result.leafstates & PAYMENT_STEP_SUCCESS);
10751077
assert(result.preimage != NULL);
10761078

1077-
ret = jsonrpc_stream_success(p->cmd);
1079+
ret = jsonrpc_stream_success(cmd);
10781080
json_add_node_id(ret, "destination", p->destination);
10791081
json_add_sha256(ret, "payment_hash", p->payment_hash);
10801082
json_add_timeabs(ret, "created_at", p->start_time);
@@ -1096,9 +1098,6 @@ static void payment_finished(struct payment *p)
10961098

10971099
json_add_string(ret, "status", "complete");
10981100

1099-
/* Unset the pointer to the cmd so we don't attempt to
1100-
* return a response twice. */
1101-
p->cmd = NULL;
11021101
if (command_finished(cmd, ret)) {/* Ignore result. */}
11031102
return;
11041103
} else if (result.failure == NULL || result.failure->failcode < NODE) {

tests/test_plugin.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,6 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
14991499
check_coin_moves_idx(l2)
15001500

15011501

1502-
@pytest.mark.xfail(strict=True)
15031502
def test_3847_repro(node_factory, bitcoind):
15041503
"""Reproduces the issue in #3847: duplicate response from plugin
15051504

0 commit comments

Comments
 (0)