contrib/init: (OpenRC) use -startupnotify to wait for startup completion #22285

pull whitslack wants to merge 1 commits into bitcoin:master from whitslack:openrc-startupnotify changing 1 files +20 −4
  1. whitslack commented at 6:22 pm on June 19, 2021: contributor

    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. The -startupnotify option was added in 090530cc24 (#15367) to support exactly this use case, so let’s use it.

    The ideal OpenRC mechanism of marking the service inactive at startup and later calling back into the start() function with IN_BACKGROUND=yes won’t work here because bitcoind runs as an unprivileged user that is not allowed to call rc-service ${SVCNAME} start, and OpenRC has no mechanism like systemd-notify, so instead we make start-stop-daemon lock a startup dummy file with flock(1) before exec’ing bitcoind, and then we use -startupnotify to release the lock when bitcoind is ready to service RPC requests. In the initscript’s start_post() function we lock the startup file briefly, which forces that function to wait until bitcoind has released its lock on the file, which will happen when bitcoind either executes the -startupnotify command or dies. After acquiring and releasing the lock, start_post() performs one final check that the pid file still exists, which allows the service to be marked as started or stopped appropriately.

  2. contrib/init: (OpenRC) use -startupnotify to wait for startup completion
    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. The -startupnotify option was added in 090530cc24
    (#15367) to support exactly this use case, so let's use it.
    
    The ideal OpenRC mechanism of marking the service inactive at startup
    and later calling back into the start() function with IN_BACKGROUND=yes
    won't work here because bitcoind runs as an unprivileged user that
    is not allowed to call "rc-service ${SVCNAME} start", and OpenRC has no
    mechanism like systemd-notify, so instead we make start-stop-daemon
    lock a startup dummy file with flock(1) before exec'ing bitcoind, and
    then we use -startupnotify to release the lock when bitcoind is ready
    to service RPC requests. In the initscript's start_post() function we
    lock the startup file briefly, which forces that function to wait until
    bitcoind has released its lock on the file, which will happen when
    bitcoind either executes the -startupnotify command or dies. After
    acquiring and releasing the lock, start_post() performs one final check
    that the pid file still exists, which allows the service to be marked
    as started or stopped appropriately.
    dad4627dfe
  3. DrahtBot added the label Scripts and tools on Jun 19, 2021
  4. luke-jr commented at 0:27 am on June 27, 2021: member
    Not sure this is a good idea. If the user starts bitcoind at boot, he will need to wait potentially an annoyingly long time before he can login…?
  5. whitslack commented at 0:34 am on June 27, 2021: contributor

    Not sure this is a good idea. If the user starts bitcoind at boot, he will need to wait potentially an annoyingly long time before he can login…?

    The other way I could do it would be to have the initscript mark the service as inactive and fork a subshell process into the background to wait for the lock and eventually reinvoke the initscript (with IN_BACKGROUND=yes) to mark the service as started so any dependent services can start in the background.

    That said, if you’re using rc_parallel=yes, then I think you’d get a login prompt before BitcoinD has finished starting anyway, assuming your login manager doesn’t (transitively) depend on bitcoind, which I can’t imagine it would.

  6. luke-jr commented at 1:46 am on June 27, 2021: member
    I’ve never seen a login prompt before all startup has completed… (console login)
  7. whitslack commented at 2:05 am on June 27, 2021: contributor

    Oh, sure. SystemV init with the default Gentoo config won’t start agetty until openrc is finished transitioning to the default runlevel.

    So, would you be more amenable to this change if I did the background thing? To be honest, that’s how I’ve had it set up on my machine for years (since long before -startupnotify was implemented), but I assumed the rather gross hackishness of that solution would be more objectionable than the straightforward approach.

  8. luke-jr commented at 5:00 am on June 27, 2021: member
    I’m not familiar enough with the tradeoffs and implementation details, but it sounds like a better solution at face value.
  9. whitslack commented at 5:02 am on June 27, 2021: contributor
    Okay, I’ll show you. Might take me a couple days to get to it.
  10. whitslack commented at 7:55 pm on June 27, 2021: contributor
  11. DrahtBot commented at 7:04 am on June 28, 2021: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #22354 (contrib/init: (OpenRC) use -startupnotify to wait for startup completion [alternative] by whitslack)

    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.

  12. laanwj commented at 10:52 am on July 7, 2021: member
    Wouldn’t -daemonwait help here? This option was added for doing a similar thing for the systemd script, and seems more straightforward.
  13. whitslack commented at 2:49 pm on July 7, 2021: contributor

    Wouldn’t -daemonwait help here? This option was added for doing a similar thing for the systemd script, and seems more straightforward. @laanwj: That’s the option I was searching for when I started out on this project, as I was certain I’d seen it mentioned in the Bitcoin Optech newsletter, but it’s not listed in --help, so I abandoned that avenue. Thanks for the pointer.

    That said, -daemonwait won’t address @luke-jr’s concern, which I addressed in an alternative way using -startupnotify in #22354.

  14. laanwj commented at 2:35 pm on August 16, 2021: member

    it’s not listed in –help, so I abandoned that avenue. Thanks for the pointer.

    Are you sure? It is mentioned in --help here:

    0  -daemonwait
    1       Wait for initialization to be finished before exiting. This implies
    2       -daemon (default: 0)
    

    It’s relatively new, so make sure you check with at least 22.x.

  15. whitslack commented at 7:33 pm on August 17, 2021: contributor

    It’s relatively new, so make sure you check with at least 22.x. @laanwj: Great! I don’t run prerelease versions of Bitcoin Core, so I haven’t seen it yet.

    Nevertheless, naïvely using -daemonwait doesn’t seem to be a good option here, as it would delay the completion of OpenRC’s switch to the default runlevel at boot and thus will delay init’s startup of agetty/login for longer than may be desirable. Perhaps it would be feasible to start bitcoind with -daemonwait in a backgrounded subshell and call back to OpenRC to mark the service as started after the bitcoind launcher process returns to the subshell. That would address @luke-jr’s concern without using -startupnotify.

  16. whitslack closed this on Jan 14, 2022

  17. whitslack deleted the branch on Jan 14, 2022
  18. DrahtBot locked this on Jan 14, 2023

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-10-06 19:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me