Project

General

Profile

Actions

Bug #597

closed

lttng-gen-tp: tracepoint provider templates fail when SystemTap and C++ are combined

Added by Daniel U. Thibault over 10 years ago. Updated over 10 years ago.

Status:
Resolved
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
07/18/2013
Due date:
% Done:

100%

Estimated time:

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.

Actions #1

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.

Actions #2

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.

Actions #3

Updated by Mathieu Desnoyers over 10 years ago

  • Project changed from LTTng to LTTng-UST
Actions #4

Updated by Yannick Brosseau over 10 years ago

We need to also change the other examples
(And look at tools for the same)

Actions #5

Updated by Mathieu Desnoyers over 10 years ago

  • Status changed from New to Resolved
  • % Done changed from 0 to 100
Actions

Also available in: Atom PDF