util/check: Add CHECK_NONFATAL identity function and NONFATAL_UNREACHABLE macro #24812

pull aureleoules wants to merge 1 commits into bitcoin:master from aureleoules:check_non_fatal_identity changing 7 files +49 −39
  1. aureleoules commented at 11:48 PM on April 8, 2022: member

    This PR replaces the macro CHECK_NONFATAL with an identity function.
    I simplified the usage of CHECK_NONFATAL where applicable in src/rpc.
    This function is useful in sanity checks for RPC and command-line interfaces.

    Context: #24804 (review).

    Also adds UNREACHABLE_NONFATAL macro.

  2. aureleoules force-pushed on Apr 9, 2022
  3. aureleoules force-pushed on Apr 9, 2022
  4. DrahtBot added the label RPC/REST/ZMQ on Apr 9, 2022
  5. DrahtBot added the label Utils/log/libs on Apr 9, 2022
  6. in src/util/check.h:98 in 5eeb1e55e5 outdated
      93 | + *
      94 | + * - Should be used to run non-fatal checks.
      95 | + * - For fatal errors, use Assert().
      96 | + * - Appropriate for non-fatal errors in interactive sessions (e.g. RPC or command line interfaces).
      97 | + */
      98 | +#define CheckNonFatal(val) inline_check_non_fatal(val, __FILE__, __LINE__, __func__, #val)
    


    MarcoFalke commented at 6:59 AM on April 9, 2022:

    I think you can just recycle the existing name. No need to add a second one.


    aureleoules commented at 9:28 AM on April 10, 2022:

    It's now replaced I had to add unreachable return statements like below otherwise the CI would complain https://github.com/bitcoin/bitcoin/blob/0661baffe8044cc049f6494ab29b79f5e4b00998/src/rpc/util.cpp#L986-L993

  7. aureleoules force-pushed on Apr 9, 2022
  8. aureleoules force-pushed on Apr 9, 2022
  9. aureleoules force-pushed on Apr 10, 2022
  10. aureleoules renamed this:
    util/check: Add CheckNonFatal identity function and use it in src/rpc
    util/check: Replace CHECK_NONFATAL macro with identity function and use it in src/rpc
    on Apr 10, 2022
  11. fanquake deleted a comment on Apr 10, 2022
  12. DrahtBot commented at 1:50 AM on April 11, 2022: member

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #24455 (refactor: Split ArgsManager out of util/system by Empact)
    • #22341 (rpc: add getxpub by Sjors)
    • #19792 (rpc: Add dumpcoinstats by fjahr)

    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.

  13. in src/wallet/rpc/backup.cpp:919 in 0661baffe8 outdated
     915 | @@ -916,6 +916,7 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
     916 |          return "unrecognized script";
     917 |      } // no default case, so the compiler can warn about missing cases
     918 |      CHECK_NONFATAL(false);
     919 | +    return ""; // not reached
    


    MarcoFalke commented at 9:35 AM on April 11, 2022:

    Hmm, I am wondering if it makes sense to introduce a macro that throws NonFatalCheckError unconditionally?

    CHECK_NONFATAL(false) is inspired by assert(false) to mark unreachable code. Though, hiding the implementation behind a function call makes it harder for the compiler to realize the function never returns when called with false. (The same happens when using Assert(false)).


    aureleoules commented at 7:36 PM on April 11, 2022:

    How about a macro UNREACHABLE_NONFATAL() and UNREACHABLE()?


    vincenzopalazzo commented at 11:37 PM on April 11, 2022:

    Hmm, I am wondering if it makes sense to introduce a macro that throws NonFatalCheckError unconditionally?

    CHECK_NONFATAL(false) is inspired by assert(false) to mark unreachable code. Though, hiding the implementation behind a function call makes it harder for the compiler to realize the function never returns when called with false. (The same happens when using Assert(false)).

    Concept ACK, this will make the code much cleaner

  14. aureleoules force-pushed on Apr 12, 2022
  15. in src/util/check.h:98 in 36654224a6 outdated
      93 | +#define NONFATAL_UNREACHABLE()                                                       \
      94 | +    do {                                                                             \
      95 | +        throw NonFatalCheckError(                                                    \
      96 | +            format_internal_error("Unreachable code reached",                        \
      97 | +                                  __FILE__, __LINE__, __func__, PACKAGE_BUGREPORT)); \
      98 | +    } while (0)
    


    vincenzopalazzo commented at 6:10 AM on April 12, 2022:
        } while (false)
    

    MarcoFalke commented at 6:18 AM on April 12, 2022:

    do-while-0 is only used when there is a need to force a trailing semicolon or to bundle several statements or "leaking" statements into one, none of which apply here, so it could be dropped as well?


    vincenzopalazzo commented at 6:23 AM on April 12, 2022:

    Concept ACK


    aureleoules commented at 11:47 AM on April 12, 2022:

    Fixed it

  16. vincenzopalazzo changes_requested
  17. vincenzopalazzo commented at 6:11 AM on April 12, 2022: none

    LGTM, but I'm not a big fan of while(0) in C++, maybe C in yes

  18. in src/util/check.h:27 in 36654224a6 outdated
      22 | +    strprintf("Internal bug detected: '%s'\n%s:%d (%s)\nPlease report this issue here: %s\n", \
      23 | +              msg, file, line, func, report)
      24 | +
      25 | +/** Helper for CHECK_NONFATAL() */
      26 | +template <typename T>
      27 | +T&& inline_check_non_fatal(T&& val, [[maybe_unused]] const char* file, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* assertion)
    


    MarcoFalke commented at 6:19 AM on April 12, 2022:

    Are the maybe_unused used or actually unused here?


    aureleoules commented at 11:47 AM on April 12, 2022:

    Removed annotations

  19. in src/util/check.h:107 in 36654224a6 outdated
     102 | + * This is used to mark code that is not yet implemented or is not yet reachable.
     103 | + */
     104 | +#define UNREACHABLE()                                                                                                                 \
     105 | +    do {                                                                                                                              \
     106 | +        std::cerr << format_internal_error("Unreachable code reached", __FILE__, __LINE__, __func__, PACKAGE_BUGREPORT) << std::endl; \
     107 | +        abort();                                                                                                                      \
    


    MarcoFalke commented at 6:20 AM on April 12, 2022:
            std::abort();                                                                                                                      \
    

    aureleoules commented at 11:48 AM on April 12, 2022:

    Fixed it

  20. MarcoFalke approved
  21. MarcoFalke commented at 6:20 AM on April 12, 2022: member

    lgtm

  22. aureleoules force-pushed on Apr 12, 2022
  23. aureleoules commented at 11:49 AM on April 12, 2022: member

    I've addressed the nits, thanks for your reviews.

  24. aureleoules renamed this:
    util/check: Replace CHECK_NONFATAL macro with identity function and use it in src/rpc
    util/check: Add CHECK_NONFATAL identity function, NONFATAL_UNREACHABLE AND UNREACHABLE macros
    on Apr 12, 2022
  25. vincenzopalazzo approved
  26. in src/util/check.h:95 in 1e4d38267f outdated
      90 | + * NONFATAL_UNREACHABLE() is a macro that is used to mark unreachable code. It throws a NonFatalCheckError.
      91 | + * This is used to mark code that is not yet implemented or is not yet reachable.
      92 | + */
      93 | +#define NONFATAL_UNREACHABLE()                            \
      94 | +    throw NonFatalCheckError(                             \
      95 | +        format_internal_error("Unreachable code reached", \
    


    jonatack commented at 12:20 PM on April 13, 2022:

    maybe

            format_internal_error("Unreachable code reached (non-fatal)", \
    
  27. in src/util/check.h:104 in 1e4d38267f outdated
      99 | + * UNREACHABLE is a macro that is used to mark unreachable code. It aborts the program.
     100 | + * This is used to mark code that is not yet implemented or is not yet reachable.
     101 | + */
     102 | +#define UNREACHABLE()                                                                                                                 \
     103 | +    do {                                                                                                                              \
     104 | +        std::cerr << format_internal_error("Unreachable code reached", __FILE__, __LINE__, __func__, PACKAGE_BUGREPORT) << std::endl; \
    


    jonatack commented at 12:44 PM on April 13, 2022:

    maybe

            std::cerr << format_internal_error("Unreachable code reached (fatal, aborting)", __FILE__, __LINE__, __func__, PACKAGE_BUGREPORT) << std::endl; \
    
  28. jonatack commented at 12:45 PM on April 13, 2022: member

    ACK 1e4d38267feb69bab20ed06367d0a0adcd211068

    Tested NONFATAL_UNREACHABLE

    error code: -1
    error message:
    Internal bug detected: 'Unreachable code reached'
    wallet/rpc/addresses.cpp:38 (operator())
    Please report this issue here: https://github.com/bitcoin/bitcoin/issues
    

    Tested UNREACHABLE

    Internal bug detected: 'Unreachable code reached'
    wallet/rpc/addresses.cpp:38 (operator())
    Please report this issue here: https://github.com/bitcoin/bitcoin/issues
    
    Aborted
    

    If you retouch, it looks like #include <util/check.h> ought to be added to /rpc/blockchain.cpp and /rpc/util.cpp as well here.

  29. in src/util/check.h:22 in 1e4d38267f outdated
      17 | @@ -18,8 +18,24 @@ class NonFatalCheckError : public std::runtime_error
      18 |      using std::runtime_error::runtime_error;
      19 |  };
      20 |  
      21 | +#define format_internal_error(msg, file, line, func, report)                                  \
      22 | +    strprintf("Internal bug detected: '%s'\n%s:%d (%s)\nPlease report this issue here: %s\n", \
    


    jonatack commented at 12:54 PM on April 13, 2022:
        strprintf("Internal bug detected: \"%s\"\n%s:%d (%s)\nPlease report this issue here: %s\n", \
    

    which would output the following, for example:

    error code: -1
    error message:
    Internal bug detected: "Unreachable code reached"
    wallet/rpc/addresses.cpp:38 (operator())
    Please report this issue here: https://github.com/bitcoin/bitcoin/issues
    
  30. aureleoules force-pushed on Apr 13, 2022
  31. aureleoules force-pushed on Apr 13, 2022
  32. jonatack commented at 2:24 PM on April 13, 2022: member

    re-ACK 63b753416abddb5f82ed32ff64a3372e65722fc2

  33. MarcoFalke commented at 11:59 AM on April 15, 2022: member

    Might be good to adjust the rpc linter as well for the new macros: #24856

    Can be done in a follow-up to avoid a conflict for now.

  34. in src/util/check.h:102 in 63b753416a outdated
      97 | +
      98 | +/**
      99 | + * UNREACHABLE is a macro that is used to mark unreachable code. It aborts the program.
     100 | + * This is used to mark code that is not yet implemented or is not yet reachable.
     101 | + */
     102 | +#define UNREACHABLE()                                                                                                                                   \
    


    MarcoFalke commented at 7:22 AM on April 16, 2022:

    This is unused and on a second thought I wonder if there is any value in it. The current code can already use assert(false) just fine. Introducing another way to write assert(false) will just lead to bike-shedding without any benefit.


    vincenzopalazzo commented at 7:42 AM on April 16, 2022:

    in favor to have a macro like UNREACHABLE is that we can the possibility to add more failures to the error message, that it is always good.

    Maybe somethings assert(false && "err message") can be a good motivation to have this macros, otherwise I agree with @MarcoFalke


    MarcoFalke commented at 7:45 AM on April 16, 2022:

    I think that this is unreachable code, so by definition it is not something that a user will (or should) ever see. So there is not much benefit in spending time to overengineer error messages and formatting of them.


    aureleoules commented at 12:44 PM on April 16, 2022:

    I think that this is unreachable code, so by definition it is not something that a user will (or should) ever see.

    It could be useful for developers modifying code and stumbling across an unreachable block as a result. Though I agree that it's not an essential feature considering assert(false) works alright.


    MarcoFalke commented at 1:01 PM on April 16, 2022:

    Developers would already know what assert(false) means and what it does. Printing PACKAGE_BUGREPORT for them also doesn't seem to add much value.


    aureleoules commented at 1:09 PM on April 16, 2022:

    Makes sense, I removed it

  35. util/check: Add CHECK_NONFATAL identity function, NONFATAL_UNREACHABLE AND UNREACHABLE macros ee02c8bd9a
  36. aureleoules force-pushed on Apr 16, 2022
  37. aureleoules renamed this:
    util/check: Add CHECK_NONFATAL identity function, NONFATAL_UNREACHABLE AND UNREACHABLE macros
    util/check: Add CHECK_NONFATAL identity function and NONFATAL_UNREACHABLE macro
    on Apr 16, 2022
  38. jonatack commented at 10:55 AM on April 18, 2022: member

    ACK ee02c8bd9aedad8cfd3c2618035fe275da025fb9

  39. in src/rpc/util.cpp:798 in ee02c8bd9a
     793 | @@ -793,7 +794,7 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const
     794 |          return;
     795 |      }
     796 |      case Type::ANY: {
     797 | -        CHECK_NONFATAL(false); // Only for testing
     798 | +        NONFATAL_UNREACHABLE(); // Only for testing
     799 |      }
    


    MarcoFalke commented at 9:37 AM on April 24, 2022:

    This will also fix a warning on current master with gcc-12:

    In file included from ./rpc/util.h:19,
                     from rpc/util.cpp:8:
    rpc/util.cpp: In member function 'void RPCResult::ToSections(Sections&, OuterType, int) const':
    ./util/check.h:34:9: warning: this statement may fall through [-Wimplicit-fallthrough=]
       34 |         if (!(condition)) {                                       \
          |         ^~
    rpc/util.cpp:796:9: note: in expansion of macro 'CHECK_NONFATAL'
      796 |         CHECK_NONFATAL(false); // Only for testing
          |         ^~~~~~~~~~~~~~
    rpc/util.cpp:798:5: note: here
      798 |     case Type::NONE: {
          |     ^~~~
    
  40. in src/util/check.h:29 in ee02c8bd9a
      24 | +
      25 | +/** Helper for CHECK_NONFATAL() */
      26 | +template <typename T>
      27 | +T&& inline_check_non_fatal(T&& val, const char* file, int line, const char* func, const char* assertion)
      28 | +{
      29 | +    if (!(val)) {
    


    MarcoFalke commented at 9:53 AM on April 24, 2022:
        if (!val) {
    

    nit: No need for ().

  41. in src/util/check.h:33 in ee02c8bd9a
      28 | +{
      29 | +    if (!(val)) {
      30 | +        throw NonFatalCheckError(
      31 | +            format_internal_error(assertion, file, line, func, PACKAGE_BUGREPORT));
      32 | +    }
      33 | +
    


    MarcoFalke commented at 9:53 AM on April 24, 2022:

    nit: no need for newline

  42. MarcoFalke approved
  43. MarcoFalke commented at 9:54 AM on April 24, 2022: member

    Looks like this also fixes a warning with gcc-12.

    ACK ee02c8bd9aedad8cfd3c2618035fe275da025fb9 🍨

    <details><summary>Show signature</summary>

    Signature:

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA512
    
    ACK ee02c8bd9aedad8cfd3c2618035fe275da025fb9 🍨
    -----BEGIN PGP SIGNATURE-----
    
    iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
    pUjsdwwArddL1iP4wywDs5YPWiBmm1hOzJSazUrpOb4gx4plkEEHXOXvGqIIwoRQ
    IPnUtiwBnIfZ7UDTHRUCgY8jeLNmlfZAtKRqd8n9V7fat6Uarmubynkz66O4C/pH
    lPV6WRkkcby+KDy01EJW10vGa0NqLg9VoxWiTIfb5LwoiyqcxnLYvJ6/Ir30GYsn
    cgG9pOIRhyYPYJQp79Q2R1fZmNe1Vi53RfxCBBkNXJI+tlMeCT7N8A6IHh239Dak
    KPQP43FDbgkhTuwDmf+RNipSqyvH0sWRTqNCei9Q6WWqwGiiRMH883GWtWO392bR
    gvkf+TmQeVoWqELVi+fFk7d+14zLJnnIvouMESjacwCEbkL5j5OKSw8WW6g0Uffb
    y5VyRSEFV02OrxMHmKFKn3UEAQm551gnILgu0ERvkKopedGXxttNdvsnj9nuYiMj
    IyPjD7MVuu+Ri6IaFtJ7jxCUGm+cPgei79bOuumTrRt/6g/+QZZnniZyhNx5oVHz
    CKvY4MQC
    =l4Sj
    -----END PGP SIGNATURE-----
    

    </details>

  44. MarcoFalke merged this on Apr 24, 2022
  45. MarcoFalke closed this on Apr 24, 2022

  46. sidhujag referenced this in commit 51ba4ab8cd on Apr 26, 2022
  47. aureleoules deleted the branch on May 20, 2022
  48. Fabcien referenced this in commit aac98988ac on Feb 3, 2023
  49. DrahtBot locked this on May 20, 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: 2026-05-01 06:14 UTC

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