-
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
bitcoind: Add -daemonwait option to wait for initialization #21007
Conversation
c886e29
to
f88aa35
Compare
Why such behavior couldn't be the default? |
I didn't do that to avoid that discussion for now 🙂 . It could always be made default at some point in the future if that's what people want. |
Concept ACK. |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
Concept ACK |
1b8856c
to
fc5cc74
Compare
Concept ACK |
fc5cc74
to
7482634
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.
Tested ACK 7482634 on macos.
With the following diff
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -780,6 +780,9 @@ static bool InitSanityCheck()
static bool AppInitServers(const util::Ref& context, NodeContext& node)
{
+ sleep(5);
+ return false;
+
const ArgsManager& args = *Assert(node.args);
RPCServer::OnStarted(&OnRPCStarted);
RPCServer::OnStopped(&OnRPCStopped);
On master
./src/bitcoind -regtest -daemon && echo running
Bitcoin Core starting
running
But it's not running
And with this change:
./src/bitcoind -regtest -daemonwait && echo running
Bitcoin Core starting
Error during initializaton - check debug.log for details
Good stuff, still have to review code change.
Thanks for testing! FWIW what I use to force a failure in
(pid is, by definition, only written in the daemon process) |
Not sure if this is true in the master branch. |
I am sure of this. I did not change this at all, and besides, it would be a bug otherwise. After all, what use is the temporary parent process' PID. |
creates |
That's not my point. My point is that it creates the PID file after daemonizing (when daemon is enabled). Sure, it also creates the PID file otherwise, that's okay. The only thing I was trying to say is that the option can be used for testing |
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.
Tested at 7482634, debug-builds cleanly for me and seems to behave as expected.
invalid path
$ ./src/bitcoind -signet -daemonwait -pid=/invalid/path
Bitcoin Core starting
Error during initializaton - check debug.log for details
(this particular case does not log anything to the debug log)
happy path
$ ./src/bitcoind -signet -daemonwait ; ./src/bitcoin-cli -signet stop
Bitcoin Core starting
Bitcoin Core stopping
debug log is as expected
2021-01-27T17:49:33Z Command-line arg: daemonwait=""
2021-01-27T17:49:33Z Command-line arg: signet=""
2021-01-27T17:49:33Z Using at most 125 automatic connections (1024 file descriptors available)
...
2021-01-27T17:49:35Z init message: Done loading
2021-01-27T17:49:35Z dnsseed thread start
2021-01-27T17:49:35Z Waiting 11 seconds before querying DNS seeds.
2021-01-27T17:49:35Z tor: Thread interrupt
2021-01-27T17:49:35Z addcon thread exit
...
2021-01-27T17:49:36Z Shutdown: done
passing -daemonwait=1
behaves (and logs) as expected as well
Ctrl-C works with a second or two of delay; it seems to not take effect until the wait is released but I'm not sure.
Thanks for testing @jonatack ,
That it doesn't log anything is peculiar ! (but unrelated to this PR, I guess, the same problem would happen with
It does respond to it? That's interesting. I thought the child process wouldn't get the SIGINT signal at all (hence my remaining TODO). That it doesn't react immediately is normal, It can't interrupt during verification of a block, for example. it's the same when interrupting a non-daemon startup. |
Tested with testnet, which is much slower than signet for me (95 sec vs 3)
Ctrl-C right after launching interrupts successfully after the same time period elapses
|
I've looked into this a bit. It looks like that until the parent process exits, the child process is still attached to the terminal (or at least, shell session), so it still gets the So there appears to be no need to do explicit signal propagation. That's neat. I'll remove that TODO and open this for review. |
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.
utACK 8e6d339
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.
tACK 8e6d339
Some nit suggestions below, feel free to ignore.
// from terminal. | ||
int fd = open("/dev/null", O_RDWR); | ||
if (fd >= 0) { | ||
bool err = dup2(fd, STDIN_FILENO) < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0; |
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.
fd
and err
can be const
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.
I'm not really sure what the common thing is to do for internal variables, do we have a const-unless-required-otherwise recommendation?
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.
Yes, I don't think it's explicitly stated, other than maybe via the C++ Code Guidelines linked to in the developer notes, but it's what I've been doing/reviewing, and seeing others say and do.
assert(result == 1); | ||
break; | ||
} | ||
int res = g_shutdown_r.TokenRead(); |
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.
res
here and line 54 can be const
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.
Approach ACK 8e6d339
8e6d339
to
b83b386
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 b83b386 reviewed diff/code, built/tested
Some nits if you retouch.
b83b386
to
9a09a49
Compare
Thanks @jonatack, have addressed the comments and re-pushed |
re-ACK 9a09a49 |
This adds a `-daemonwait` flag that does the same as `-daemon` except it, from a user perspective, backgrounds the process only after initialization is complete. This can be useful when the process launching bitcoind wants to guarantee that either the RPC server is running, or that initialization failed, before continuing. The exit code indicates the initialization result. This replaces the use of the libc function `daemon()` by a custom implementation which is inspired by the glibc implementation, but also creates a pipe from the child to the parent process for communication. An additional advantage of having our own `daemon()` implementation is that no MACOS-specific pragmas are needed anymore to silence a deprecation warning.
9a09a49
to
e017a91
Compare
Repushed for an ordering issue in |
Tested ACK e017a91 checked change since previous review is move-only
|
4d008f9 Always add -daemonwait to known command line arguments (Hennadii Stepanov) Pull request description: This is a follow up of #21007. When `AC_CHECK_DECLS([fork])` fails: - on master (8e65320): ``` $ src/bitcoind -daemonwait Error: Error parsing command line arguments: Invalid parameter -daemonwait ``` - with this PR: ``` $ src/bitcoind -daemonwait Error: -daemon is not supported on this operating system ``` ACKs for top commit: laanwj: Code review ACK 4d008f9 Tree-SHA512: 7fcb5e9d76958adcf57e04fa74bd2a98d62459d81a3c57a97bd74c346cbf47c53e560a15455fb024e912c3b44e8487a83499e993b282871ba069953e665d88a9
…uments 4d008f9 Always add -daemonwait to known command line arguments (Hennadii Stepanov) Pull request description: This is a follow up of bitcoin#21007. When `AC_CHECK_DECLS([fork])` fails: - on master (8e65320): ``` $ src/bitcoind -daemonwait Error: Error parsing command line arguments: Invalid parameter -daemonwait ``` - with this PR: ``` $ src/bitcoind -daemonwait Error: -daemon is not supported on this operating system ``` ACKs for top commit: laanwj: Code review ACK 4d008f9 Tree-SHA512: 7fcb5e9d76958adcf57e04fa74bd2a98d62459d81a3c57a97bd74c346cbf47c53e560a15455fb024e912c3b44e8487a83499e993b282871ba069953e665d88a9
…uments 4d008f9 Always add -daemonwait to known command line arguments (Hennadii Stepanov) Pull request description: This is a follow up of bitcoin#21007. When `AC_CHECK_DECLS([fork])` fails: - on master (8e65320): ``` $ src/bitcoind -daemonwait Error: Error parsing command line arguments: Invalid parameter -daemonwait ``` - with this PR: ``` $ src/bitcoind -daemonwait Error: -daemon is not supported on this operating system ``` ACKs for top commit: laanwj: Code review ACK 4d008f9 Tree-SHA512: 7fcb5e9d76958adcf57e04fa74bd2a98d62459d81a3c57a97bd74c346cbf47c53e560a15455fb024e912c3b44e8487a83499e993b282871ba069953e665d88a9
When other initscripts depend on bitcoind, it's because their daemons want to be able to invoke bitcoin-cli or to communicate with bitcoind via RPC. That can't happen until some time after bitcoind has forked into the background when it is started with the -daemon option. The -daemonwait option was added in 92cf3a2 (bitcoin#21007) to address exactly this issue, so let's use it. To avoid blocking startup for arbitrarily long, as users would be annoyed if agetty/display-manager doesn't start quickly, we now mark the bitcoind service initially as inactive at startup and then call back to OpenRC to mark the service as started (and proceed to start any dependent services) after bitcoind forks into the background.
This change was part of 22.0, removing "Needs release note". |
This adds a
-daemonwait
flag that does the same as-daemon
except that it, from a user perspective, backgrounds the process only after initialization is complete. This is similar to the behaviour of some other software such as c-lightning.This can be useful when the process launching bitcoind wants to guarantee that either the RPC server is running, or that initialization failed, before continuing. The exit code indicates the initialization result.
The use of the libc function
daemon()
is replaced by a custom implementation which is inspired by the glibc implementation, but which also creates a pipe from the child to the parent process for communication.An additional advantage of having our own
daemon()
implementation is that no MACOS-specific pragmas are needed anymore to silence a deprecation warning.TODO:
Factor out
token_read
andtoken_write
to an utility, and use them inshutdown.cpp
as well—this is exactly the same kind of communication mechanism.Improve granularity of the
configure.ac
checks. This currently still checks for the functiondaemon()
which makes no sense as it's not used. It should check for individual functions such asfork()
andsetsid()
etc—the former being required, the second optional.[-]
Signal propagation during initialization: if say, pressing Ctrl-C duringThis is not necessary, see bitcoind: Add -daemonwait option to wait for initialization #21007 (comment).-daemonwait
it would be good to pass this SIGINT on to the child process instead of detaching the parent process and letting the child run free.Future: