tests: Handle test failures for ust-constructors with heap allocation
authorKienan Stewart <kstewart@efficios.com>
Wed, 7 Feb 2024 20:49:26 +0000 (15:49 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 7 Mar 2024 17:03:05 +0000 (12:03 -0500)
Observed issue
==============

A number of tests from `ust/ust-constructor/test_ust_constructor.py`
fail when compiled with gcc-4.8 (observed on SLES12SP5). Eg.

```
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 8 - Found
expected event name="tp_a:constructor_c_provider_static_archive"
msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 10 - Found expected event name="tp_a:constructor_cplusplus_provider_static_archive" msg="global - static archive define and provider"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 11 - Found expected event name="tp:constructor_c_across_units_before_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 12 - Found expected event name="tp:constructor_cplusplus" msg="global - across units before define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 13 - Found expected event name="tp:constructor_c_same_unit_before_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 14 - Found expected event name="tp:constructor_c_same_unit_after_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 15 - Found expected event name="tp:constructor_cplusplus" msg="global - same unit before define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 16 - Found expected event name="tp:constructor_cplusplus" msg="global - same unit after define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 17 - Found expected event name="tp:constructor_c_across_units_after_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 18 - Found expected event name="tp:constructor_cplusplus" msg="global - across units after define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 19 - Found expected event name="tp:constructor_c_same_unit_before_provider" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 20 - Found expected event name="tp:constructor_c_same_unit_after_provider" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 21 - Found
expected event name="tp:constructor_cplusplus" msg="global - same unit
before provider"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 34 - Found expected event name="tp:destructor_cplusplus" msg="global - same unit before provider"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 35 - Found expected event name="tp:destructor_cplusplus" msg="global - across units after define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 36 - Found expected event name="tp:destructor_cplusplus" msg="global - same unit after define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 37 - Found expected event name="tp:destructor_cplusplus" msg="global - same unit before define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 38 - Found expected event name="tp:destructor_cplusplus" msg="global - across units before define"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 39 - Found
expected event
name="tp_a:destructor_cplusplus_provider_static_archive" msg="global -
static archive define and provider"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 41 - Found expected event name="tp:destructor_c_across_units_after_provider" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 42 - Found expected event name="tp:destructor_c_same_unit_after_provider" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 43 - Found expected event name="tp:destructor_c_same_unit_before_provider" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 44 - Found expected event name="tp:destructor_c_across_units_after_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 45 - Found expected event name="tp:destructor_c_same_unit_after_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 46 - Found expected event name="tp:destructor_c_same_unit_before_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 47 - Found expected event name="tp:destructor_c_across_units_before_define" msg="None"
12:22:17 FAIL: ust/ust-constructor/test_ust_constructor.py 48 - Found expected event name="tp_a:destructor_c_provider_static_archive" msg="None"
```

Cause
=====

As gcc-4.8 and earlier don't support C99 compound literals, the
lttngust `ust-compiler.h` falls back to using heap allocated
compound literals[1][2].

The probe registration in these cases is done via a C++ object[3].

As C-style constructors are executed before the C++ runtime is
processed, the probe is not yet registered[4].

In a case where g++ <= 4.8 is being used or
`-DLTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP` is defined, the
following tracepoints will not be recorded:

* C-style constructors and destructors in statically linked archives
* C-style constructors and destructors in the application itself
* Some C++ constructors and destructors invoked during the
initialization of the static global variables
  * Note: this depends on the initialization order both between translation
  units, which is not specified, and the initialization order (usually
  lexicographical) within a given translation unit.

This is a known limitation; however, the test does not support
verifying that it's being run in a such a situation.

Solution
========

A small program has been added which returns a different status code
depending on whether `LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP` is
defined or not.

The test script uses this application to signal that certain events
may fail (in that they may be present, or they may be absent).

Drawbacks
=========

None.

References
==========

[1]: https://github.com/lttng/lttng-ust/commit/e1904921db97b70d94e69f0ab3264c6f7fe62f32
[2]: https://github.com/lttng/lttng-ust/commit/7edfc1722684982b9df894c054d69808dc588a6a
[3]: https://github.com/lttng/lttng-ust/commit/05bfa3dc3a6e6b2ece3686a5f384b6645c2a5010
[4]: https://github.com/lttng/lttng-ust/blob/3287f48be61ef3491aff0a80b7185ac57b3d8a5d/include/lttng/ust-compiler.h#L110

Change-Id: I49159df4f85126c641aaf5fb0a8b5b22fd91bf12
Signed-off-by: Kienan Stewart <kstewart@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
.gitignore
tests/regression/ust/ust-constructor/test_ust_constructor.py
tests/utils/testapp/gen-ust-events-constructor/Makefile.am
tests/utils/testapp/gen-ust-events-constructor/uses_heap.cpp [new file with mode: 0644]

index eb2873e011bc0baf5d1e927ba48a6b9ad223f923..152c2baf89dbe0878de12310cd4e09971153f8eb 100644 (file)
@@ -101,6 +101,7 @@ compile_commands.json
 /tests/regression/tools/filtering/gen-ust-events
 /tests/utils/testapp/gen-ust-events/gen-ust-events
 /tests/utils/testapp/gen-ust-events-constructor/gen-ust-events-constructor
+/tests/utils/testapp/gen-ust-events-constructor/uses_heap
 /tests/utils/testapp/gen-ust-events-ns/gen-ust-events-ns
 /tests/regression/tools/health/health_check
 /tests/regression/kernel/select_poll_epoll
index d7818186c08f9815a2cc79f59e697583e6c052d7..f4d9cedf04b86cab779d1f2bb997931843596914 100755 (executable)
@@ -8,6 +8,7 @@
 import pathlib
 import sys
 import os
+import subprocess
 from typing import Any, Callable, Type
 
 """
@@ -25,9 +26,34 @@ sys.path.append(str(test_utils_import_path))
 import lttngtest
 import bt2
 
+# Determine if LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP is set. This will
+# affect if certain events may or may not be expected when compiling with
+# C++.
+# @see https://github.com/lttng/lttng-ust/blob/47fa3e4ed7ab43e034dc61fc1480f919f4ee51d0/include/lttng/ust-compiler.h#L51
+#
+compound_literal_on_heap = False
+process = subprocess.Popen(
+    [
+        os.path.join(
+            str(test_utils_import_path),
+            "testapp",
+            "gen-ust-events-constructor",
+            "uses_heap",
+        )
+    ]
+)
+process.wait()
+if process.returncode == 0:
+    compound_literal_on_heap = True
+
 expected_events = [
     {"name": "tp_so:constructor_c_provider_shared_library", "msg": None, "count": 0},
-    {"name": "tp_a:constructor_c_provider_static_archive", "msg": None, "count": 0},
+    {
+        "name": "tp_a:constructor_c_provider_static_archive",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
     {
         "name": "tp_so:constructor_cplusplus_provider_shared_library",
         "msg": "global - shared library define and provider",
@@ -37,37 +63,73 @@ expected_events = [
         "name": "tp_a:constructor_cplusplus_provider_static_archive",
         "msg": "global - static archive define and provider",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_across_units_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_across_units_before_define", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - across units before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_same_unit_before_define", "msg": None, "count": 0},
-    {"name": "tp:constructor_c_same_unit_after_define", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_across_units_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_across_units_after_define", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - across units after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_before_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_after_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_same_unit_before_provider", "msg": None, "count": 0},
-    {"name": "tp:constructor_c_same_unit_after_provider", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit before provider",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:constructor_cplusplus",
@@ -117,45 +179,91 @@ expected_events = [
         "name": "tp:destructor_cplusplus",
         "msg": "global - same unit before provider",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - across units after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - same unit after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - same unit before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - across units before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp_a:destructor_cplusplus_provider_static_archive",
         "msg": "global - static archive define and provider",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp_so:destructor_cplusplus_provider_shared_library",
         "msg": "global - shared library define and provider",
         "count": 0,
     },
-    {"name": "tp:destructor_c_across_units_after_provider", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_after_provider", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_before_provider", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_across_units_after_define", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_after_define", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_before_define", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_across_units_before_define", "msg": None, "count": 0},
-    {"name": "tp_a:destructor_c_provider_static_archive", "msg": None, "count": 0},
+    {
+        "name": "tp:destructor_c_across_units_after_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_after_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_before_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_across_units_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_across_units_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp_a:destructor_c_provider_static_archive",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
     {"name": "tp_so:destructor_c_provider_shared_library", "msg": None, "count": 0},
 ]
 
@@ -244,12 +352,16 @@ def validate_trace(trace_location, tap):
             )
 
     for event in expected_events:
-        tap.test(
-            event["count"] == 1,
-            'Found expected event name="{}" msg="{}"'.format(
-                event["name"], str(event["msg"])
+        may_fail = "may_fail" in event.keys() and event["may_fail"]
+        if not may_fail:
+            tap.test(
+                event["count"] == 1,
+                'Found expected event name="{}" msg="{}"'.format(
+                    event["name"], str(event["msg"])
+                ),
             ),
-        )
+        else:
+            tap.skip("Event '{}' may or may not be recorded".format(event["name"]))
 
     tap.test(unknown_event_count == 0, "Found no unexpected events")
 
index 4e7e1e1021576da8db846e4d074b411ec9851608..b323baee2f2fb449f0644d0890fc707063c8e603 100644 (file)
@@ -48,9 +48,9 @@ libtp_a_define_la_SOURCES = \
        tp-a-define.cpp \
        tp-a.h
 
-noinst_PROGRAMS = gen-ust-events-constructor
-gen_ust_events_constructor_SOURCES = \
-       main.cpp \
+noinst_PROGRAMS = gen-ust-events-constructor \
+       uses_heap
+gen_ust_events_constructor_SOURCES = main.cpp \
        01-tp-before-define.cpp \
        02-define-tp.cpp \
        03-tp-after-define.cpp \
@@ -66,4 +66,6 @@ gen_ust_events_constructor_LDADD = $(UST_LIBS) \
                $(builddir)/libtp-a-provider.la \
                $(top_builddir)/tests/utils/libtestutils.la \
                $(DL_LIBS)
+
+uses_heap_SOURCES = uses_heap.cpp
 endif
diff --git a/tests/utils/testapp/gen-ust-events-constructor/uses_heap.cpp b/tests/utils/testapp/gen-ust-events-constructor/uses_heap.cpp
new file mode 100644 (file)
index 0000000..35933de
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2024 Kienan Stewart <kstewart@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+
+#include <lttng/ust-compiler.h>
+
+int main()
+{
+#ifdef LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP
+       return 0;
+#else
+       return 1;
+#endif
+}
This page took 0.031452 seconds and 4 git commands to generate.