Skip to content

Commit aa9cb51

Browse files
committed
json-rpc: Shutdown the JSON-RPC in the context of a DB transaction
This needs to be done separately from the rest of the daemon since we can otherwise not make sure that it happens before the DB is freed and we might still need the DN, and be running in a DB transaction, for some destructors to run.
1 parent 5e2ed79 commit aa9cb51

File tree

4 files changed

+20
-8
lines changed

4 files changed

+20
-8
lines changed

lightningd/jsonrpc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ static void parse_request(struct json_connection *jcon, const jsmntok_t tok[])
447447

448448
/* This is a convenient tal parent for duration of command
449449
* (which may outlive the conn!). */
450-
c = tal(jcon->ld, struct command);
450+
c = tal(jcon->ld->rpc_listener, struct command);
451451
c->jcon = jcon;
452452
c->ld = jcon->ld;
453453
c->pending = false;
@@ -650,8 +650,7 @@ void setup_jsonrpc(struct lightningd *ld, const char *rpc_filename)
650650
err(1, "Listening on '%s'", rpc_filename);
651651

652652
log_debug(ld->log, "Listening on '%s'", rpc_filename);
653-
/* Technically this is a leak, but there's only one */
654-
notleak(io_new_listener(ld, fd, incoming_jcon_connected, ld));
653+
ld->rpc_listener = io_new_listener(ld->rpc_filename, fd, incoming_jcon_connected, ld);
655654
}
656655

657656
/**
@@ -790,4 +789,3 @@ bool json_tok_wtx(struct wallet_tx * tx, const char * buffer,
790789
}
791790
return true;
792791
}
793-

lightningd/lightningd.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,14 @@ int main(int argc, char *argv[])
455455
}
456456

457457
shutdown_subdaemons(ld);
458+
459+
/* Clean up the JSON-RPC. This needs to happen in a DB transaction since
460+
* it might actually be touching the DB in some destructors, e.g.,
461+
* unreserving UTXOs (see #1737) */
462+
db_begin_transaction(ld->wallet->db);
463+
tal_free(ld->rpc_listener);
464+
db_commit_transaction(ld->wallet->db);
465+
458466
close(pid_fd);
459467
remove(ld->pidfile);
460468

lightningd/lightningd.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,15 @@ struct lightningd {
7878

7979
/* Our config dir, and rpc file */
8080
char *config_dir;
81+
82+
/* Location of the RPC socket. */
8183
char *rpc_filename;
8284

85+
/* The listener for the RPC socket. Can be shut down separately from the
86+
* rest of the daemon to allow a clean shutdown, which frees all pending
87+
* cmds in a DB transaction. */
88+
struct io_listener *rpc_listener;
89+
8390
/* Configuration file name */
8491
char *config_filename;
8592
/* Configuration settings. */

tests/test_rpc.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from fixtures import * # noqa: F401,F403
22

33
import os
4-
import pytest
54
import signal
65
import unittest
76

@@ -11,13 +10,13 @@
1110
DEVELOPER = os.getenv("DEVELOPER", config['DEVELOPER']) == "1"
1211

1312

14-
@pytest.mark.xfail(strict=True)
1513
@unittest.skipIf(not DEVELOPER, "needs --dev-disconnect")
1614
def test_stop_pending_fundchannel(node_factory, executor):
1715
"""Stop the daemon while waiting for an accept_channel
1816
19-
This used to crash the node, since we were calling unreserve_utxo while freeing
20-
the daemon, but that needs a DB transaction to be open.
17+
This used to crash the node, since we were calling unreserve_utxo while
18+
freeing the daemon, but that needs a DB transaction to be open.
19+
2120
"""
2221
l1 = node_factory.get_node()
2322
l2 = node_factory.get_node()

0 commit comments

Comments
 (0)