rpc: uptime should begin on application start #34437

pull l0rinc wants to merge 1 commits into bitcoin:master from l0rinc:l0rinc/fix-uptime-first-call-zero changing 2 files +9 −6
  1. l0rinc commented at 10:54 pm on January 28, 2026: contributor

    Problem

    #34328 switched uptime to use monotonic time, but g_startup_time was a function-local static in GetUptime(), meaning it was initialized on first call rather than at program start. This caused the first uptime RPC to always return 0.

    Fix

    Move g_startup_time to namespace scope so it initializes at program start, ensuring the first uptime() call returns actual elapsed time.

    Reproducer

    Revert the fix and run the test or alternatively:

    0cmake -B build && cmake --build build --target bitcoind bitcoin-cli -j$(nproc)
    1./build/bin/bitcoind -regtest -daemon
    2sleep 10
    3./build/bin/bitcoin-cli -regtest uptime
    4./build/bin/bitcoin-cli -regtest stop
    
    0Bitcoin Core starting
    10
    2Bitcoin Core stopping
    
    0Bitcoin Core starting
    110
    2Bitcoin Core stopping
    

    Fixes #34423, added reporter as coauthor.

  2. DrahtBot added the label RPC/REST/ZMQ on Jan 28, 2026
  3. DrahtBot commented at 10:55 pm on January 28, 2026: contributor

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

    Reviews

    See the guideline for information on the review process.

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    LLM Linter (✨ experimental)

    Possible places where comparison-specific test macros should replace generic comparisons:

    • test/functional/rpc_uptime.py: “assert uptime_before > 0, "uptime should begin at app start"” -> Use assert_greater_than(uptime_before, 0) instead of a bare assert.

    2026-01-29 18:54:12

  4. luke-jr referenced this in commit ece1c1a838 on Jan 29, 2026
  5. in src/common/system.cpp:41 in 44cf02bea9
    36@@ -37,6 +37,10 @@
    37 
    38 using util::ReplaceAll;
    39 
    40+namespace {
    41+    const auto g_startup_time{SteadyClock::now()};
    


    sedited commented at 10:12 am on January 29, 2026:
    Why not just declare this static?

    sedited commented at 11:32 am on January 29, 2026:
    Because it is just used in this single translation unit: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rs-unnamed2 ,

    l0rinc commented at 11:35 am on January 29, 2026:
    Yes, my IDE explicitly warned about that:

    l0rinc commented at 6:54 pm on January 29, 2026:

    Added to the commit message:

    Move g_startup_time to namespace scope so it initializes at program start, ensuring the first call returns actual elapsed time. Note that we don’t need to make it static anymore because it is just used in this single translation unit.

  6. in test/functional/rpc_uptime.py:31 in 44cf02bea9 outdated
    25@@ -26,8 +26,11 @@ def _test_negative_time(self):
    26         assert_raises_rpc_error(-8, "Mocktime must be in the range [0, 9223372036], not -1.", self.nodes[0].setmocktime, -1)
    27 
    28     def _test_uptime(self):
    29-        wait_time = 20_000
    30+        time.sleep(1) # Do some work before checking uptime
    31         uptime_before = self.nodes[0].uptime()
    32+        assert uptime_before > 0, "uptime should begin at app start"
    


    maflcko commented at 6:45 pm on January 29, 2026:

    nit: Would be nice to use the util helpers consistently:

    assert uptime_before > 0, "uptime should begin at app start" -> Use assert_greater_than(uptime_before, 0) (replace bare assert with the functional test helper).
    

    l0rinc commented at 6:50 pm on January 29, 2026:
    On failure that would only show the values not fulfilling the comparison, not why the uptime should be positive (“uptime should begin at app start”)

    maflcko commented at 9:57 am on January 30, 2026:
    It does print the reason, if it is placed in a comment after the assertion. However, I don’t think printing it is important and the comment can also be on the line above. If you think allowing to print reasons for those helpers, it should be trivial to add that feature.

    l0rinc commented at 10:00 am on January 30, 2026:
    I have tried modifying them before and they were nacked. If someone else wants to, I can review it, but I’m not planning on using them as they are now, I think they’re very noisy

    maflcko commented at 10:11 am on January 30, 2026:
    I think the project should try to converge to a common style for newly written code (this is also explained in the dev notes). If you think the style is wrong, it can be changed, but I don’t think it is great, if everyone is brewing their own soup and going against the dev notes.

    l0rinc commented at 10:12 am on January 30, 2026:
    agree, that’s what I tried in that PR, converge to a common style.
  7. in src/common/system.cpp:42 in 44cf02bea9
    36@@ -37,6 +37,10 @@
    37 
    38 using util::ReplaceAll;
    39 
    40+namespace {
    41+    const auto g_startup_time{SteadyClock::now()};
    42+} // namespace
    


    maflcko commented at 6:47 pm on January 29, 2026:
    nit: Could move this right next to the only function that uses it

    l0rinc commented at 6:54 pm on January 29, 2026:

    Déjà vu :D

    I did it originally to minimize the diff - but we’re past that now, so it makes sense.

  8. maflcko commented at 6:47 pm on January 29, 2026: member
    lgtm ACK 44cf02bea99ce429033df6035386f252d5992706
  9. fix: uptime RPC returns 0 on first call
    The monotonic uptime fix (#34328) used a function-local static for `g_startup_time`, which was initialized on first `GetUptime()` call instead of app startup time.
    This caused the first `uptime()` call to always return 0.
    
    Move `g_startup_time` to namespace scope so it initializes at program start, ensuring the first call returns actual elapsed time. Note that we don't need to make it `static` anymore because it is just used in this single translation unit.
    
    Test was updated to simulate some work before the first call.
    
    Co-authored-by: Carlo Antinarella <carloantinarella@users.noreply.github.com>
    e67a676df9
  10. l0rinc force-pushed on Jan 29, 2026
  11. maflcko commented at 7:40 pm on January 29, 2026: member
    lgtm ACK e67a676df9af5ece5307438ae1b4ddb0730e3482
  12. optout21 commented at 2:02 pm on February 2, 2026: contributor
    crACK e67a676df9af5ece5307438ae1b4ddb0730e3482
  13. luke-jr referenced this in commit c202961b8e on Feb 2, 2026
  14. l0rinc commented at 8:32 pm on February 4, 2026: contributor
    rfm?
  15. musaHaruna commented at 11:30 am on February 5, 2026: contributor

    Tested ACK e67a676

    ./build/test/functional/rpc_uptime.py uptime results (before and after) before this PR

    0Uptime before: 0
    1Uptime after: 0
    

    ./build/test/functional/rpc_uptime.py uptime results (before and after) with this PR

    0Uptime before: 1
    1Uptime after: 1
    

    My understanding of the change in this PR: Before the PR, both uptime before and uptime after were reported as 0 because the previous implementation stored the startup time as a static variable inside GetUptime(), which initializes only when the function is first called; at that moment, g_startup_time and SteadyClock::now() are effectively equal, so subtracting them always yields zero. After the PR, g_startup_time is initialized once at program start in a global anonymous namespace, so SteadyClock::now() - g_startup_time now correctly measures the elapsed runtime from program launch. For example, if the program starts at monotonic time 100 seconds and one second passes, calling GetUptime() returns 101 − 100 = 1 second. This confirms that uptime now begins counting at program start and is immune to wall-clock jumps (from #34328), producing correct, monotonic results. I’m open to feedback if this understanding is incorrect.

  16. maflcko added this to the milestone 31.0 on Feb 5, 2026
  17. carloantinarella commented at 8:32 pm on February 5, 2026: contributor
    Tested ACK e67a676df9af5ece5307438ae1b4ddb0730e3482 Built and tested manually the same way I did in #34328 (comment). Works fine.
  18. achow101 commented at 0:56 am on February 6, 2026: member
    ACK e67a676df9af5ece5307438ae1b4ddb0730e3482
  19. achow101 merged this on Feb 6, 2026
  20. achow101 closed this on Feb 6, 2026

  21. l0rinc deleted the branch on Feb 6, 2026

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: 2026-02-22 00:13 UTC

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