mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
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.
This commit is contained in:
parent
ead0c8e17a
commit
d6048de100
@ -447,7 +447,7 @@ static void parse_request(struct json_connection *jcon, const jsmntok_t tok[])
|
|||||||
|
|
||||||
/* This is a convenient tal parent for duration of command
|
/* This is a convenient tal parent for duration of command
|
||||||
* (which may outlive the conn!). */
|
* (which may outlive the conn!). */
|
||||||
c = tal(jcon->ld, struct command);
|
c = tal(jcon->ld->rpc_listener, struct command);
|
||||||
c->jcon = jcon;
|
c->jcon = jcon;
|
||||||
c->ld = jcon->ld;
|
c->ld = jcon->ld;
|
||||||
c->pending = false;
|
c->pending = false;
|
||||||
@ -650,8 +650,7 @@ void setup_jsonrpc(struct lightningd *ld, const char *rpc_filename)
|
|||||||
err(1, "Listening on '%s'", rpc_filename);
|
err(1, "Listening on '%s'", rpc_filename);
|
||||||
|
|
||||||
log_debug(ld->log, "Listening on '%s'", rpc_filename);
|
log_debug(ld->log, "Listening on '%s'", rpc_filename);
|
||||||
/* Technically this is a leak, but there's only one */
|
ld->rpc_listener = io_new_listener(ld->rpc_filename, fd, incoming_jcon_connected, ld);
|
||||||
notleak(io_new_listener(ld, fd, incoming_jcon_connected, ld));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -790,4 +789,3 @@ bool json_tok_wtx(struct wallet_tx * tx, const char * buffer,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +462,14 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
shutdown_subdaemons(ld);
|
shutdown_subdaemons(ld);
|
||||||
|
|
||||||
|
/* Clean up the JSON-RPC. This needs to happen in a DB transaction since
|
||||||
|
* it might actually be touching the DB in some destructors, e.g.,
|
||||||
|
* unreserving UTXOs (see #1737) */
|
||||||
|
db_begin_transaction(ld->wallet->db);
|
||||||
|
tal_free(ld->rpc_listener);
|
||||||
|
db_commit_transaction(ld->wallet->db);
|
||||||
|
|
||||||
close(pid_fd);
|
close(pid_fd);
|
||||||
remove(ld->pidfile);
|
remove(ld->pidfile);
|
||||||
|
|
||||||
|
@ -78,8 +78,15 @@ struct lightningd {
|
|||||||
|
|
||||||
/* Our config dir, and rpc file */
|
/* Our config dir, and rpc file */
|
||||||
char *config_dir;
|
char *config_dir;
|
||||||
|
|
||||||
|
/* Location of the RPC socket. */
|
||||||
char *rpc_filename;
|
char *rpc_filename;
|
||||||
|
|
||||||
|
/* The listener for the RPC socket. Can be shut down separately from the
|
||||||
|
* rest of the daemon to allow a clean shutdown, which frees all pending
|
||||||
|
* cmds in a DB transaction. */
|
||||||
|
struct io_listener *rpc_listener;
|
||||||
|
|
||||||
/* Configuration file name */
|
/* Configuration file name */
|
||||||
char *config_filename;
|
char *config_filename;
|
||||||
/* Configuration settings. */
|
/* Configuration settings. */
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
from fixtures import * # noqa: F401,F403
|
from fixtures import * # noqa: F401,F403
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pytest
|
|
||||||
import signal
|
import signal
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@ -11,13 +10,13 @@ with open('config.vars') as configfile:
|
|||||||
DEVELOPER = os.getenv("DEVELOPER", config['DEVELOPER']) == "1"
|
DEVELOPER = os.getenv("DEVELOPER", config['DEVELOPER']) == "1"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(strict=True)
|
|
||||||
@unittest.skipIf(not DEVELOPER, "needs --dev-disconnect")
|
@unittest.skipIf(not DEVELOPER, "needs --dev-disconnect")
|
||||||
def test_stop_pending_fundchannel(node_factory, executor):
|
def test_stop_pending_fundchannel(node_factory, executor):
|
||||||
"""Stop the daemon while waiting for an accept_channel
|
"""Stop the daemon while waiting for an accept_channel
|
||||||
|
|
||||||
This used to crash the node, since we were calling unreserve_utxo while freeing
|
This used to crash the node, since we were calling unreserve_utxo while
|
||||||
the daemon, but that needs a DB transaction to be open.
|
freeing the daemon, but that needs a DB transaction to be open.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
l1 = node_factory.get_node()
|
l1 = node_factory.get_node()
|
||||||
l2 = node_factory.get_node()
|
l2 = node_factory.get_node()
|
||||||
|
Loading…
Reference in New Issue
Block a user