| 167 | } |
| 168 | |
| 169 | static bool AppInit(NodeContext& node) |
| 170 | { |
| 171 | bool fRet = false; |
| 172 | ArgsManager& args = *Assert(node.args); |
| 173 | |
| 174 | #if HAVE_DECL_FORK |
| 175 | // Communication with parent after daemonizing. This is used for signalling in the following ways: |
| 176 | // - a boolean token is sent when the initialization process (all the Init* functions) have finished to indicate |
| 177 | // that the parent process can quit, and whether it was successful/unsuccessful. |
| 178 | // - an unexpected shutdown of the child process creates an unexpected end of stream at the parent |
| 179 | // end, which is interpreted as failure to start. |
| 180 | TokenPipeEnd daemon_ep; |
| 181 | #endif |
| 182 | std::any context{&node}; |
| 183 | try |
| 184 | { |
| 185 | // -server defaults to true for bitcoind but not for the GUI so do this here |
| 186 | args.SoftSetBoolArg("-server", true); |
| 187 | // Set this early so that parameter interactions go to console |
| 188 | InitLogging(args); |
| 189 | InitParameterInteraction(args); |
| 190 | if (!AppInitBasicSetup(args, node.exit_status)) { |
| 191 | // InitError will have been called with detailed error, which ends up on console |
| 192 | return false; |
| 193 | } |
| 194 | if (!AppInitParameterInteraction(args)) { |
| 195 | // InitError will have been called with detailed error, which ends up on console |
| 196 | return false; |
| 197 | } |
| 198 | |
| 199 | node.warnings = std::make_unique<node::Warnings>(); |
| 200 | |
| 201 | node.kernel = std::make_unique<kernel::Context>(); |
| 202 | node.ecc_context = std::make_unique<ECC_Context>(); |
| 203 | if (!AppInitSanityChecks(*node.kernel)) |
| 204 | { |
| 205 | // InitError will have been called with detailed error, which ends up on console |
| 206 | return false; |
| 207 | } |
| 208 | |
| 209 | if (args.GetBoolArg("-daemon", DEFAULT_DAEMON) || args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) { |
| 210 | #if HAVE_DECL_FORK |
| 211 | tfm::format(std::cout, CLIENT_NAME " starting\n"); |
| 212 | |
| 213 | // Daemonize |
| 214 | switch (fork_daemon(1, 0, daemon_ep)) { // don't chdir (1), do close FDs (0) |
| 215 | case 0: // Child: continue. |
| 216 | // If -daemonwait is not enabled, immediately send a success token the parent. |
| 217 | if (!args.GetBoolArg("-daemonwait", DEFAULT_DAEMONWAIT)) { |
| 218 | daemon_ep.TokenWrite(1); |
| 219 | daemon_ep.Close(); |
| 220 | } |
| 221 | break; |
| 222 | case -1: // Error happened. |
| 223 | return InitError(Untranslated(strprintf("fork_daemon() failed: %s", SysErrorString(errno)))); |
| 224 | default: { // Parent: wait and exit. |
| 225 | int token = daemon_ep.TokenRead(); |
| 226 | if (token) { // Success |
no test coverage detected