Bug #597
closedlttng-gen-tp: tracepoint provider templates fail when SystemTap and C++ are combined
100%
Description
I have a small C++ application that demonstrates LTTng instrumentation (user-space tracepoints). However, when I try to make it after installing SystemTap, the make fails badly:
error: template with C linkage error: template specialization with C linkage (28 times) error: template with C linkage (twice)
This occurs starting at sdt.h
line 71. A little investigation reveals the problem is caused by sdt.h
using C++ templates (the templates are within an #ifdef __cplusplus
block). C++ templates cannot be inside an extern "C"
block (it's a peculiarity of the C++ spec; see http://stackoverflow.com/questions/4877705/why-cant-templates-be-within-extern-c-blocks for the details). tracepoint.h
correctly calls sdt.h
before entering its own extern "C"
block, but the lttng-ust/doc/examples/easy-ust/sample_component_provider.h
wraps its call to #include <lttng/tracepoint.h>
in such a block. Hence kablooie.
It looks like the tracepoint provider header should change from:
#undef TRACEPOINT_PROVIDER #define TRACEPOINT_PROVIDER sample_component #undef TRACEPOINT_INCLUDE #define TRACEPOINT_INCLUDE "./tp.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #if !defined(_SAMPLE_COMPONENT_PROVIDER_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define _SAMPLE_COMPONENT_PROVIDER_H #include <lttng/tracepoint.h> [...]
To:
#undef TRACEPOINT_PROVIDER #define TRACEPOINT_PROVIDER sample_component #undef TRACEPOINT_INCLUDE #define TRACEPOINT_INCLUDE "./tp.h" #include <lttng/tracepoint.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #if !defined(_SAMPLE_COMPONENT_PROVIDER_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define _SAMPLE_COMPONENT_PROVIDER_H [...]
This moves the #include <lttng/tracepoint.h>
line up and out of the extern "C"
block. Maybe the _SAMPLE_COMPONENT_PROVIDER_H
line should move along, I don't know for sure.
I rebuilt my various samples using this modified tracepoint provider header and everything now works as it did before SystemTap was installed.
If this is indeed the correct fix (maybe there are other circumstances that justify keeping the #include <lttng/tracepoint.h>
inside an extern "C"
block), then lttng-gen-tp
will need to be modified. So will the sample tracepoint provider headers in lttng-ust/doc/examples
.
Updated by Daniel U. Thibault over 10 years ago
Come to think about it, the correct sequence would be:
/* * Add this precompiler conditional to ensure the tracepoint event generation * can include this file more than once. */ #if !defined(_SAMPLE_COMPONENT_PROVIDER_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define _SAMPLE_COMPONENT_PROVIDER_H /* * Add this to allow programs to call "tracepoint(...)": */ #include <lttng/tracepoint.h> /* * Add this macro and its matching element to make sure the program * works in C++. */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* * The following tracepoint event writes a message (C string) into the * field "message" of the trace event "event" in the provider * "sample_component" in other words: * * sample_component:event:message = text. */ TRACEPOINT_EVENT( [...]
Because we need to keep the #include <lttng/tracepoint.h>
inside the #if !defined(_SAMPLE_COMPONENT_PROVIDER_H)
block.
Updated by Daniel U. Thibault over 10 years ago
For proper nesting:
#undef TRACEPOINT_PROVIDER #define TRACEPOINT_PROVIDER sample_component #undef TRACEPOINT_INCLUDE #define TRACEPOINT_INCLUDE "./tp.h" #if !defined(_SAMPLE_COMPONENT_PROVIDER_H) || defined(TRACEPOINT_HEADER_MULTI_READ) #define _SAMPLE_COMPONENT_PROVIDER_H #include <lttng/tracepoint.h> #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ TRACEPOINT_EVENT( [...] ) TRACEPOINT_LOGLEVEL( [...] ) #ifdef __cplusplus } #endif /* __cplusplus */ #include <lttng/tracepoint-event.h> #endif /* _SAMPLE_COMPONENT_PROVIDER_H */
The #include <lttng/tracepoint-event.h>
can safely be outside the extern "C"
because it tests for __cplusplus
itself. But it should be inside the #if !defined(_SAMPLE_COMPONENT_PROVIDER_H)
because there is no point in having it included when <lttng/tracepoint.h>
isn't.
Updated by Mathieu Desnoyers over 10 years ago
- Project changed from LTTng to LTTng-UST
Updated by Yannick Brosseau over 10 years ago
We need to also change the other examples
(And look at tools for the same)
Updated by Mathieu Desnoyers over 10 years ago
- Status changed from New to Resolved
- % Done changed from 0 to 100
Applied in changeset 177d5e84ca824cd51c41cc380b0f7600e27e39a6.