-
Notifications
You must be signed in to change notification settings - Fork 36.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
util: Add -shutdownnotify option #23395
Conversation
dc2ef7c
to
c44960e
Compare
c44960e
to
df9fde8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK df9fde8
This PR adds a new (optional) argument -shutdownnotify
to bitcoind that allows passing of custom user command when bitcoin core is shut down.
I tested this PR using the testing method suggested by @klementtan. I have added a screenshot showing that the proper working of the -shutdownnotify
command.
This command has many use cases, especially the one @klementtan
explained where users could notify themselves if bitcoin core unexpectedly closes. Considering the usefulness of this command, I agree with the changes made in this PR.
I have one thing to ask, though:
Can a command like “./src/bitcoind -signet” be given as the value for this argument? If no, then why so?
When I tried to use this argument value myself, there was no output whatsoever.
I understand the motivation however this option can be misused IMO so not sure about adding it I was reading the comments in #15367 and I think we should even remove Observation: Although we can run almost everything as this option allows shell commands but I was experimenting if its possible to keep Bitcoin Core running and never shutdown. Worked intermittently but nothing interesting.
If getting notifications on start and shutdown is the goal maybe we should not provide easy option to execute shell commands with it. A file with name |
Thanks, @prayank23 and @shaavan for the review and pointing out the edge case where a user might supply A solution for that would be to call Open to feedback on how we should handle the scenario when a user supplies
If you view |
I think we can avoid this case. It was just an observation which looked interesting initially. If a user wants to experiment and provides such argument he should be able to kill process or reboot system. I have issues with an option in Bitcoin Core that triggers any shell command based on start/shutdown. This feature can be helpful for lot of people with malicious intent. |
@prayank23 If an attacker manages to make you invoke |
Concept ACK |
@sipa Yes victim will have bigger problems depending on the case. Are we helping attackers with this feature? Example: Attacker: We have a new airdrop where you don't need to share any credentials with us. It will be distributed to all bitcoin holders however they need to restart Please run:
Victim: Restarts core with command shared by attacker Attacker: Gets reverse shell |
@prayank23 This is a known and obvious issue with all |
Can you explain this a bit more? The current code will notify users after Bitcoin Core expectedly shuts down, that is, after telling it to shutdown. If users want to find out if it unexpectedly shut down, they will need to check for the absence of the notification and verify that the process is not running (e.g. writing state (utxo, wallet, ...) to the disk on shutdown). |
There is probably a difference still between unexpected shutdowns and unclean shutdowns. E.g. when disk is full, Bitcoin Core will (possibly) shut down cleanly, but it's not explicitly requested by the user. |
@MarcoFalke yup similar to what @sipa pointed out, this would be useful for users who wish to be notified when Bitcoin Core cleanly shuts down without being explicitly requested by the user. Updated the PR description to clearly describe what does unexpected means. |
Concept ACK I think it is important to get #22417 merged first, though - otherwise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be good to run commands synchronously and before shutdown begins - that way they have the opportunity to perform pre-shutdown RPC calls and such?
a13e4cf
to
5a64663
Compare
5a64663
to
812910e
Compare
812910e
to
2d8a11b
Compare
Concept ACK |
2d8a11b
to
1f4382d
Compare
Not opposed to this but please don't mis-advertise it;
Yes, there is no way to monitor for unexpected shutdowns from within bitcoind itself. This is theoretically and practically impossible no matter how hard you try. One way to do this is to tell the OS to receive notifications when the process dies, e.g. in Linux one can use |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
579f1a4
to
fcc7cf7
Compare
This seems like a good idea, is straightforward, and has a couple of ACKs and some concept ACKs. Concept ACK, seems it could use a functional test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion to rename config option based on #23412 (comment)
static void ShutdownNotify(const ArgsManager& args) | ||
{ | ||
std::vector<std::thread> threads; | ||
for (const auto& cmd : args.GetArgs("-shutdownnotify")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (const auto& cmd : args.GetArgs("-shutdownnotify")) { | |
for (const auto& cmd : args.GetArgs("-executeonshutdown")) { |
@@ -405,6 +421,7 @@ void SetupServerArgs(ArgsManager& argsman) | |||
argsman.AddArg("-settings=<file>", strprintf("Specify path to dynamic settings data file. Can be disabled with -nosettings. File is written at runtime and not meant to be edited by users (use %s instead for custom settings). Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME, BITCOIN_SETTINGS_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | |||
#if HAVE_SYSTEM | |||
argsman.AddArg("-startupnotify=<cmd>", "Execute command on startup.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | |||
argsman.AddArg("-shutdownnotify=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
argsman.AddArg("-shutdownnotify=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); | |
argsman.AddArg("-executeonshutdown=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be best to keep as-is, to mirror the other notify command
Are you still working on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK fcc7cf7
fcc7cf7
to
d96d97a
Compare
Apologies for the delay. Added an additional functional test in the latest patch git range-diff fcc7cf7~2..fcc7cf7 d96d97a~2..d96d97a1: 46790135b ! 1: 0bd73e2c4 util: Add -shutdownnotify option.
@@ src/init.cpp: void SetupServerArgs(ArgsManager& argsman)
#endif
#ifndef WIN32
argsman.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
## test/functional/feature_notifications.py ##
@@ test/functional/feature_notifications.py: class NotificationsTest(BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = True
# The experimental syscall sandbox feature (-sandbox) is not compatible with -alertnotify,
- # -blocknotify or -walletnotify (which all invoke execve).
+ # -blocknotify, -walletnotify or -shutdownnotify (which all invoke execve).
self.disable_syscall_sandbox = True
def setup_network(self):
@@ test/functional/feature_notifications.py: class NotificationsTest(BitcoinTestFramework):
self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
+ self.shutdownnotify_dir = os.path.join(self.options.tmpdir, "shutdownnotify")
+ self.shutdownnotify_file = os.path.join(self.shutdownnotify_dir, "shutdownnotify.txt")
os.mkdir(self.alertnotify_dir)
os.mkdir(self.blocknotify_dir)
os.mkdir(self.walletnotify_dir)
+ os.mkdir(self.shutdownnotify_dir)
# -alertnotify and -blocknotify on node0, walletnotify on node1
self.extra_args = [[
f"-alertnotify=echo > {os.path.join(self.alertnotify_dir, '%s')}",
f"-blocknotify=echo > {os.path.join(self.blocknotify_dir, '%s')}",
+ f"-shutdownnotify=echo > {self.shutdownnotify_file}",
], [
f"-walletnotify=echo %h_%b > {os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s'))}",
]]
@@ test/functional/feature_notifications.py: class NotificationsTest(BitcoinTestFramework):
# TODO: add test for `-alertnotify` large fork notifications
+ self.log.info("test -shutdownnotify")
+ self.stop_nodes()
+ self.wait_until(lambda: os.path.isfile(self.shutdownnotify_file), timeout=10)
+
def expect_wallet_notify(self, tx_details):
self.wait_until(lambda: len(os.listdir(self.walletnotify_dir)) >= len(tx_details), timeout=10)
# Should have no more and no less files than expected
2: fcc7cf751 = 2: d96d97ad3 doc: Add release note for shutdownnotify. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reACK d96d97a
No clue about test because I do all my testing outside this framework.
ACK d96d97a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK d96d97a
However, I would not not be responsible for misuse of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK d96d97a
The only change since my previous ACK was the added functional test. Retested also on OpenBSD 7.1 ✔️
d96d97a doc: Add release note for shutdownnotify. (klementtan) 0bd73e2 util: Add -shutdownnotify option. (klementtan) Pull request description: **Description**: Similar to `-startupnotify`, this PR adds a new option to allow users to specify a command to be executed when Bitcoin Core shuts down. **Note**: The `shutdownnotify` commands will not be executed if bitcoind shut down due to *unexpected* reasons (ie `killall -9 bitcoind`). ### Testing: **Normal shutdown commands** ``` # start bitcoind with shutdownnotify optioin ./src/bitcoind -signet -shutdownnotify="touch foo.txt" # shutdown bitcoind ./src/bitcoin-cli -signet stop # check that foo.txt has been created ``` **Final RPC call** Commands: ``` $ ./src/bitcoind -signet -nolisten -noconnect -shutdownnotify="./src/bitcoin-cli -signet getblockchaininfo > tmp.txt" $ ./src/bitcoin-cli stop $ cat tmp.txt ``` <details> <summary>Screen Shot</summary> ![image](https://user-images.githubusercontent.com/49265907/141186183-cbc6f82c-400d-4a8b-baba-27c0346c2c8a.png) </details> ACKs for top commit: achow101: ACK d96d97a 1440000bytes: ACK bitcoin@d96d97a theStack: re-ACK d96d97a Tree-SHA512: 16f7406fd232e8b97aea5e58854c84755b0c35c88cb3ef9ee123b29a1475a376122b1e100da860cc336d4d657e6046a70e915fdb9b70c9fd097c6eef1b028161
Description: Similar to
-startupnotify
, this PR adds a new option to allow users to specify a command to be executed when Bitcoin Core shuts down.Note: The
shutdownnotify
commands will not be executed if bitcoind shut down due to unexpected reasons (iekillall -9 bitcoind
).Testing:
Normal shutdown commands
Final RPC call
Commands:
Screen Shot