Skip to content

Commit

Permalink
json-rpc: Shutdown the JSON-RPC in the context of a DB transaction
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cdecker committed Jul 26, 2018
1 parent ead0c8e commit d6048de
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 8 deletions.
6 changes: 2 additions & 4 deletions lightningd/jsonrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* (which may outlive the conn!). */
c = tal(jcon->ld, struct command);
c = tal(jcon->ld->rpc_listener, struct command);
c->jcon = jcon;
c->ld = jcon->ld;
c->pending = false;
Expand Down Expand Up @@ -650,8 +650,7 @@ void setup_jsonrpc(struct lightningd *ld, const char *rpc_filename)
err(1, "Listening on '%s'", rpc_filename);

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

/**
Expand Down Expand Up @@ -790,4 +789,3 @@ bool json_tok_wtx(struct wallet_tx * tx, const char * buffer,
}
return true;
}

8 changes: 8 additions & 0 deletions lightningd/lightningd.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,14 @@ int main(int argc, char *argv[])
}

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);
remove(ld->pidfile);

Expand Down
7 changes: 7 additions & 0 deletions lightningd/lightningd.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,15 @@ struct lightningd {

/* Our config dir, and rpc file */
char *config_dir;

/* Location of the RPC socket. */
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 */
char *config_filename;
/* Configuration settings. */
Expand Down
7 changes: 3 additions & 4 deletions tests/test_rpc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from fixtures import * # noqa: F401,F403

import os
import pytest
import signal
import unittest

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


@pytest.mark.xfail(strict=True)
@unittest.skipIf(not DEVELOPER, "needs --dev-disconnect")
def test_stop_pending_fundchannel(node_factory, executor):
"""Stop the daemon while waiting for an accept_channel
This used to crash the node, since we were calling unreserve_utxo while freeing
the daemon, but that needs a DB transaction to be open.
This used to crash the node, since we were calling unreserve_utxo while
freeing the daemon, but that needs a DB transaction to be open.
"""
l1 = node_factory.get_node()
l2 = node_factory.get_node()
Expand Down

0 comments on commit d6048de

Please sign in to comment.