Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/collector/python/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import (

/*
#include <datadog_agent_rtloader.h>
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static
*/
import "C"
Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/python/datadog_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import (
)

/*
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static

#include "datadog_agent_rtloader.h"
Expand Down
5 changes: 4 additions & 1 deletion pkg/collector/python/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import (
)

/*
#cgo !windows LDFLAGS: -L${SRCDIR}/../../../rtloader/build/rtloader -ldatadog-agent-rtloader -ldl
// On AIX, Go's CGO requires shared libraries to be wrapped in .a archives.
// libdatadog-agent-rtloader.a is built from the .so file using "ar -X64 -r".
#cgo aix LDFLAGS: -L${SRCDIR}/../../../rtloader/build/rtloader -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -L${SRCDIR}/../../../rtloader/build/rtloader -ldatadog-agent-rtloader -ldl
#cgo windows LDFLAGS: -L${SRCDIR}/../../../rtloader/build/rtloader -ldatadog-agent-rtloader -lstdc++ -static
#cgo CFLAGS: -I "${SRCDIR}/../../../rtloader/include" -I "${SRCDIR}/../../../rtloader/common"

Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/python/init_nix.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (
)

/*
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl

#include <datadog_agent_rtloader.h>
#include <rtloader_mem.h>
Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/python/kubeutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import (

/*
#include <datadog_agent_rtloader.h>
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static
*/
import "C"
Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/python/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import (
)

/*
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static

#if defined(__linux__) || defined(_WIN32)
Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/python/no_kubeutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ package python

/*
#include <datadog_agent_rtloader.h>
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static
*/
import "C"
Expand Down
73 changes: 73 additions & 0 deletions pkg/collector/python/python_aix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

//go:build aix && python

package python

// Force libpython.so into the agent binary's XCOFF startup-load chain.
//
// Background
// ----------
// Python C extension modules (lib-dynload/_decimal.so, etc.) carry Python API
// symbols (PyArg_ParseTuple, PyBool_FromLong, …) with no explicit library
// dependency in their XCOFF loader section (IMPid = "."). On AIX, such
// unresolved symbols are looked up in the process-global symbol table, which
// is populated only by libraries that appear in the XCOFF startup-load chain
// (i.e. in the XCOFF loader section of the main executable or its startup-
// linked dependencies).
//
// Without this file, libpython.so is loaded only via dlopen, transitively
// through libdatadog-agent-three.so when rtloader initialises Python. A
// dlopen-loaded library does NOT add its symbols to the global symbol table.
// As a result every Python C extension fails with:
//
// ImportError: Symbol PyXxx is not exported from dependent module agent.
//
// Fix
// ---
// The init() function below calls C.Py_IsInitialized() once at process startup.
// Go's CGO layer sees this Go→C call and emits a //go:cgo_import_dynamic
// directive that places libpython.a(shr_64.o) in the agent binary's XCOFF
// loader section. Consequently libpython.so is loaded at process startup,
// before any Python C extension module is imported, and all Python API
// symbols enter the global symbol table where the extension modules can find them.
//
// Note: a C-internal reference (static void* holding &Py_IsInitialized) is NOT
// sufficient — Go's linker only generates XCOFF import entries for symbols that
// are called from the Go side through CGO. A direct Go→C call is required.
//
// Py_IsInitialized() returns 0 when called here (Python not yet started) and
// has no side effects — it is a safe, idempotent read of an internal flag.
//
// Part 2 — Exporting Python API symbols from the agent binary
// The -bE:python.exp flag (passed via CGO_LDFLAGS at build time, NOT via
// #cgo LDFLAGS which would be rejected by Go's CGO security filter) causes the
// linker to add all Python API symbols to the agent binary's own EXP
// (export) table. Extension modules have Python API symbols with IMPid="."
// in their XCOFF, meaning "find in the main program's EXP table". Without
// -bE, those symbols are not exported from the agent and every extension fails:
//
// ImportError: Symbol PyXxx is not exported from dependent module agent.
//
// With -bE:python.exp, the agent exports the symbols and extensions load cleanly.

/*
#cgo LDFLAGS: -L${SRCDIR}/../../../embedded/lib -lpython3

// Forward declaration — we do not include Python.h to avoid pulling in
// the entire CPython header tree; Py_IsInitialized has a stable ABI.
extern int Py_IsInitialized(void);
*/
import "C"

func init() {
// Call Py_IsInitialized() to create a live Go→C reference. This forces
// the CGO linker to emit a //go:cgo_import_dynamic for Py_IsInitialized,
// placing libpython.a(shr_64.o) in the XCOFF startup-load chain.
// Python is not yet started here so the call always returns 0; we discard
// the result. There are no side effects.
_ = C.Py_IsInitialized()
}
3 changes: 2 additions & 1 deletion pkg/collector/python/tagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (
)

/*
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static

#include "datadog_agent_rtloader.h"
Expand Down
3 changes: 2 additions & 1 deletion pkg/collector/python/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ package python

/*
#include <datadog_agent_rtloader.h>
#cgo !windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo !aix,!windows LDFLAGS: -ldatadog-agent-rtloader -ldl
#cgo aix LDFLAGS: -ldl
#cgo windows LDFLAGS: -ldatadog-agent-rtloader -lstdc++ -static
*/
import "C"
Expand Down
8 changes: 7 additions & 1 deletion rtloader/rtloader/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
# define DATADOG_AGENT_THREE "libdatadog-agent-three.dylib"
#elif __FreeBSD__
# define DATADOG_AGENT_THREE "libdatadog-agent-three.so"
#elif _AIX
# define DATADOG_AGENT_THREE "libdatadog-agent-three.so"
#elif _WIN32
# define DATADOG_AGENT_THREE "libdatadog-agent-three.dll"
#else
Expand Down Expand Up @@ -404,7 +406,11 @@ DATADOG_AGENT_RTLOADER_API int handle_crashes(const int enable_coredump, const i
if (alt_stack == nullptr) {
// Note: this memory is never freed, but it is necessary for the duration of the program
alt_stack = _malloc(alt_stack_size);
stack_t new_stack{ .ss_sp = alt_stack, .ss_flags = 0, .ss_size = alt_stack_size };
stack_t new_stack;
memset(&new_stack, 0, sizeof(new_stack));
new_stack.ss_sp = (decltype(new_stack.ss_sp))alt_stack;
new_stack.ss_size = alt_stack_size;
new_stack.ss_flags = 0;
Comment on lines -407 to +413

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fields are not ordered the same way on AIX and Linux, and some types also change, so this is a simple way to fix that without having to use macros

int ret = sigaltstack(&new_stack, nullptr);
if (ret != 0) {
std::ostringstream err_msg;
Expand Down
Loading