[PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds

Juergen Gross posted 1 patch 1 year, 8 months ago
Test gitlab-ci failed
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/20220824102225.11431-1-jgross@suse.com
xen/include/xen/lib.h | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
[PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Juergen Gross 1 year, 8 months ago
Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
builds a warning seems to be appropriate when hitting one.

In order not to flood the console in reproducible cases, introduce
WARN_ONCE() to be used in this case.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
Notice for the release manager: this patch isn't really urgent for the
4.17 release, OTOH it is adding probably useful debug information for
the unlikely case of hitting an ASSERT_UNREACHABLE(). The risk for
taking the patch should be rather low, but you have the last saying,
of course.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 xen/include/xen/lib.h | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index 05ee1e18af..b8472d753c 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -40,6 +40,16 @@
     unlikely(ret_warn_on_);             \
 })
 
+#define WARN_ONCE() do {                \
+    static bool warned = false;         \
+                                        \
+    if ( !warned )                      \
+    {                                   \
+        warned = true;                  \
+        WARN();                         \
+    }                                   \
+} while (0)
+
 /* All clang versions supported by Xen have _Static_assert. */
 #if defined(__clang__) || \
     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
@@ -63,7 +73,7 @@
 #define ASSERT_UNREACHABLE() assert_failed("unreachable")
 #else
 #define ASSERT(p) do { if ( 0 && (p) ) {} } while (0)
-#define ASSERT_UNREACHABLE() do { } while (0)
+#define ASSERT_UNREACHABLE() WARN_ONCE()
 #endif
 
 #define ABS(_x) ({                              \
-- 
2.35.3
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Jan Beulich 1 year, 8 months ago
On 24.08.2022 12:22, Juergen Gross wrote:
> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
> builds a warning seems to be appropriate when hitting one.

I disagree, for two reasons: This violates the implication of NDEBUG
meaning ASSERT() and friends expand to no actual code. Plus if doing so
for ASSERT_UNREACHABLE(), why would we not do the same for ASSERT()?
There's a reason we have ASSERT() and friends and, independently,
WARN_ON() / BUG_ON() et al.

Jan
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Andrew Cooper 1 year, 8 months ago
On 24/08/2022 11:35, Jan Beulich wrote:
> On 24.08.2022 12:22, Juergen Gross wrote:
>> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
>> builds a warning seems to be appropriate when hitting one.
> I disagree, for two reasons: This violates the implication of NDEBUG
> meaning ASSERT() and friends expand to no actual code.

I agree.  ASSERT() and friends should no code in !DEBUG builds.

Furthermore, if an ASSERT_UNREACHALBE() is proving to be problematic
even at runtime, then it's not the correct construct in the first place.

~Andrew
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Juergen Gross 1 year, 8 months ago
On 24.08.22 12:35, Jan Beulich wrote:
> On 24.08.2022 12:22, Juergen Gross wrote:
>> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
>> builds a warning seems to be appropriate when hitting one.
> 
> I disagree, for two reasons: This violates the implication of NDEBUG
> meaning ASSERT() and friends expand to no actual code. Plus if doing so

This is something we can change IMHO.

> for ASSERT_UNREACHABLE(), why would we not do the same for ASSERT()?

There are multiple reasons to have ASSERT()s. Some serve as a kind of
documentation (e.g. to document that the programmer thought of a special
case not being possible), or they are meant to catch hard to diagnose
bugs rather early instead of letting them hit later in a situation where
it wouldn't be clear what caused them. Adding a WARN() for all of these
cases isn't really appropriate, especially as this might impact
performance due to added tests, which isn't the case for theoretically
unreachable code.

> There's a reason we have ASSERT() and friends and, independently,
> WARN_ON() / BUG_ON() et al.

We might want to introduce something like ASSERT_OR_WARN(). I'm sure
this could be useful in some cases.


Juergen
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Jan Beulich 1 year, 8 months ago
On 24.08.2022 12:45, Juergen Gross wrote:
> On 24.08.22 12:35, Jan Beulich wrote:
>> On 24.08.2022 12:22, Juergen Gross wrote:
>>> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
>>> builds a warning seems to be appropriate when hitting one.
>>
>> I disagree, for two reasons: This violates the implication of NDEBUG
>> meaning ASSERT() and friends expand to no actual code. Plus if doing so
> 
> This is something we can change IMHO.
> 
>> for ASSERT_UNREACHABLE(), why would we not do the same for ASSERT()?
> 
> There are multiple reasons to have ASSERT()s. Some serve as a kind of
> documentation (e.g. to document that the programmer thought of a special
> case not being possible), or they are meant to catch hard to diagnose
> bugs rather early instead of letting them hit later in a situation where
> it wouldn't be clear what caused them. Adding a WARN() for all of these
> cases isn't really appropriate, especially as this might impact
> performance due to added tests, which isn't the case for theoretically
> unreachable code.
> 
>> There's a reason we have ASSERT() and friends and, independently,
>> WARN_ON() / BUG_ON() et al.
> 
> We might want to introduce something like ASSERT_OR_WARN(). I'm sure
> this could be useful in some cases.

I'm curious why in such cases it can't just be WARN_ON().

Jan
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Juergen Gross 1 year, 8 months ago
On 24.08.22 13:12, Jan Beulich wrote:
> On 24.08.2022 12:45, Juergen Gross wrote:
>> On 24.08.22 12:35, Jan Beulich wrote:
>>> On 24.08.2022 12:22, Juergen Gross wrote:
>>>> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
>>>> builds a warning seems to be appropriate when hitting one.
>>>
>>> I disagree, for two reasons: This violates the implication of NDEBUG
>>> meaning ASSERT() and friends expand to no actual code. Plus if doing so
>>
>> This is something we can change IMHO.
>>
>>> for ASSERT_UNREACHABLE(), why would we not do the same for ASSERT()?
>>
>> There are multiple reasons to have ASSERT()s. Some serve as a kind of
>> documentation (e.g. to document that the programmer thought of a special
>> case not being possible), or they are meant to catch hard to diagnose
>> bugs rather early instead of letting them hit later in a situation where
>> it wouldn't be clear what caused them. Adding a WARN() for all of these
>> cases isn't really appropriate, especially as this might impact
>> performance due to added tests, which isn't the case for theoretically
>> unreachable code.
>>
>>> There's a reason we have ASSERT() and friends and, independently,
>>> WARN_ON() / BUG_ON() et al.
>>
>> We might want to introduce something like ASSERT_OR_WARN(). I'm sure
>> this could be useful in some cases.
> 
> I'm curious why in such cases it can't just be WARN_ON().

It won't result in test failure of debug builds.

In the end I'm not feeling really strong here, so I'm fine to drop this
patch.


Juergen
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Bertrand Marquis 1 year, 8 months ago
Hi,

> On 24 Aug 2022, at 11:35, Jan Beulich <jbeulich@suse.com> wrote:
> 
> On 24.08.2022 12:22, Juergen Gross wrote:
>> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
>> builds a warning seems to be appropriate when hitting one.
> 
> I disagree, for two reasons: This violates the implication of NDEBUG
> meaning ASSERT() and friends expand to no actual code. Plus if doing so
> for ASSERT_UNREACHABLE(), why would we not do the same for ASSERT()?
> There's a reason we have ASSERT() and friends and, independently,
> WARN_ON() / BUG_ON() et al.

I agree with Jan here, this is introducing code in ASSERT which is not the intention
and will end up with dead code in production mode.

In NDEBUG those should appear.

If something is needed or we think there could be a situation where this is reachable,
then the code should be modified to use something else then ASSERT[_UNREACHABLE]().

Bertrand

> 
> Jan
> 
Re: [PATCH] xen: let ASSERT_UNREACHABLE() WARN() in non-debug builds
Posted by Julien Grall 1 year, 8 months ago
Hi Juergen,

Thanks for sending the patch quickly :).

On 24/08/2022 11:22, Juergen Gross wrote:
> Hitting an ASSERT_UNREACHABLE() is always wrong, so even in production
> builds a warning seems to be appropriate when hitting one.
> 
> In order not to flood the console in reproducible cases, introduce
> WARN_ONCE() to be used in this case.
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>

Acked-by: Julien Grall <jgrall@amazon.com>

Cheers,

-- 
Julien Grall