mirror of https://github.com/bitcoin/bitcoin.git
init: Signal m_tip_block_cv on Ctrl-C
Signal m_tip_block_cv when Ctrl-C is pressed or SIGTERM is received, the same way it is currently signalled when the `stop` RPC is called. This lets RPC calls like `waitforblockheight` and IPC calls like `waitTipChanged` be interrupted, instead of waiting for their original timeouts and delaying shutdown. Historical notes: - The behavior where `stop` RPC signals `m_tip_block_cv`, but CTRL-C does not, has been around since the condition variable was introduced in #30409 (7eccdaf160
). - The signaling was later moved without changing behavior in #30967 (5ca28ef28b
). This commit moves it again to the Interrupt() function, which is probably the place it should have been added initially, so it works for Ctrl-C shutdowns as well as `stop` shutdowns. - A Qt shutdown bug calling wait methods was fixed previously in #18452 (da73f1513a
), and this change updates that fix to avoid the hang happening again in Qt.
This commit is contained in:
parent
6a29f79006
commit
c25a5e670b
|
@ -215,8 +215,6 @@ void InitContext(NodeContext& node)
|
||||||
node.shutdown_request = [&node] {
|
node.shutdown_request = [&node] {
|
||||||
assert(node.shutdown_signal);
|
assert(node.shutdown_signal);
|
||||||
if (!(*node.shutdown_signal)()) return false;
|
if (!(*node.shutdown_signal)()) return false;
|
||||||
// Wake any threads that may be waiting for the tip to change.
|
|
||||||
if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all());
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -267,6 +265,8 @@ void Interrupt(NodeContext& node)
|
||||||
#if HAVE_SYSTEM
|
#if HAVE_SYSTEM
|
||||||
ShutdownNotify(*node.args);
|
ShutdownNotify(*node.args);
|
||||||
#endif
|
#endif
|
||||||
|
// Wake any threads that may be waiting for the tip to change.
|
||||||
|
if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all());
|
||||||
InterruptHTTPServer();
|
InterruptHTTPServer();
|
||||||
InterruptHTTPRPC();
|
InterruptHTTPRPC();
|
||||||
InterruptRPC();
|
InterruptRPC();
|
||||||
|
|
|
@ -132,7 +132,6 @@ public:
|
||||||
}
|
}
|
||||||
void appShutdown() override
|
void appShutdown() override
|
||||||
{
|
{
|
||||||
Interrupt(*m_context);
|
|
||||||
Shutdown(*m_context);
|
Shutdown(*m_context);
|
||||||
}
|
}
|
||||||
void startShutdown() override
|
void startShutdown() override
|
||||||
|
@ -141,12 +140,7 @@ public:
|
||||||
if (!(Assert(ctx.shutdown_request))()) {
|
if (!(Assert(ctx.shutdown_request))()) {
|
||||||
LogError("Failed to send shutdown signal\n");
|
LogError("Failed to send shutdown signal\n");
|
||||||
}
|
}
|
||||||
|
Interrupt(*m_context);
|
||||||
// Stop RPC for clean shutdown if any of waitfor* commands is executed.
|
|
||||||
if (args().GetBoolArg("-server", false)) {
|
|
||||||
InterruptRPC();
|
|
||||||
StopRPC();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bool shutdownRequested() override { return ShutdownRequested(*Assert(m_context)); };
|
bool shutdownRequested() override { return ShutdownRequested(*Assert(m_context)); };
|
||||||
bool isSettingIgnored(const std::string& name) override
|
bool isSettingIgnored(const std::string& name) override
|
||||||
|
|
|
@ -12,7 +12,6 @@ import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from test_framework.authproxy import JSONRPCException
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.test_node import (
|
from test_framework.test_node import (
|
||||||
BITCOIN_PID_FILENAME_DEFAULT,
|
BITCOIN_PID_FILENAME_DEFAULT,
|
||||||
|
@ -251,9 +250,8 @@ class InitTest(BitcoinTestFramework):
|
||||||
terminal. (This can be different than the node shutdown sequence that
|
terminal. (This can be different than the node shutdown sequence that
|
||||||
happens when the stop RPC is sent.)
|
happens when the stop RPC is sent.)
|
||||||
|
|
||||||
Currently when the break signal is sent, it does not interrupt the
|
The waitforblockheight call should be interrupted and return right away,
|
||||||
waitforblockheight RPC call, and the node does not exit until it times
|
and not time out."""
|
||||||
out."""
|
|
||||||
|
|
||||||
self.log.info("Testing waitforblockheight RPC call followed by break signal")
|
self.log.info("Testing waitforblockheight RPC call followed by break signal")
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
|
@ -287,12 +285,9 @@ class InitTest(BitcoinTestFramework):
|
||||||
node.process.send_signal(signal.SIGTERM)
|
node.process.send_signal(signal.SIGTERM)
|
||||||
node.process.wait()
|
node.process.wait()
|
||||||
|
|
||||||
try:
|
result = fut.result()
|
||||||
result = fut.result()
|
self.log.debug(f"waitforblockheight returned {result!r}")
|
||||||
raise Exception(f"waitforblockheight returned {result!r}")
|
assert_equal(result["height"], current_height)
|
||||||
except JSONRPCException as e:
|
|
||||||
self.log.debug(f"waitforblockheight raised {e!r}")
|
|
||||||
assert_equal(e.error['code'], -344) # -344 is RPC timeout
|
|
||||||
node.wait_until_stopped()
|
node.wait_until_stopped()
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
|
|
Loading…
Reference in New Issue