Skip to content

Commit

Permalink
get latest changes from upstream (#8)
Browse files Browse the repository at this point in the history
* meta: Bump python dependencies (getsentry#600)

The old version of pytest breaks with python 3.10 which changed a
little how code object internals work.  Since python 3.10 is now
released it starts being used in CI.

* fix: Ensure that a valid DSN has a public_key (getsentry#598)

* feat: AIX support (getsentry#593)

Co-authored-by: Floris Bruynooghe <[email protected]>
Co-authored-by: Arpad Borsos <[email protected]>
Co-authored-by: Calvin Buckley <[email protected]>
  • Loading branch information
4 people authored Oct 22, 2021
1 parent 90966cc commit e76411c
Show file tree
Hide file tree
Showing 24 changed files with 601 additions and 48 deletions.
13 changes: 12 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/sentry")

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LINUX TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400")
set(AIX TRUE)
endif()

#setup sentry library type
Expand Down Expand Up @@ -84,7 +86,7 @@ endif()

if(WIN32)
set(SENTRY_DEFAULT_TRANSPORT "winhttp")
elseif((APPLE AND NOT IOS) OR LINUX)
elseif((APPLE AND NOT IOS) OR LINUX OR AIX)
set(SENTRY_DEFAULT_TRANSPORT "curl")
else()
set(SENTRY_DEFAULT_TRANSPORT "none")
Expand Down Expand Up @@ -248,6 +250,15 @@ else()
endif()
target_compile_definitions(sentry PRIVATE SIZEOF_LONG=${CMAKE_SIZEOF_LONG})

# AIX needs libm for isnan used in test suite
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400")
target_link_libraries(sentry PRIVATE m)
endif()
# On IBM i PASE, flock is in libutil. Here because "sentry" exists now.
if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
target_link_libraries(sentry PRIVATE util)
endif()

if(SENTRY_TRANSPORT_CURL)
find_package(CURL REQUIRED)
if(TARGET CURL::libcurl) # Only available in cmake 3.12+
Expand Down
7 changes: 7 additions & 0 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ has_arg(int argc, char **argv, const char *arg)
return false;
}

#ifdef SENTRY_PLATFORM_AIX
// AIX has a null page mapped to the bottom of memory, which means null derefs
// don't segfault. try dereferencing the top of memory instead; the top nibble
// seems to be unusable.
static void *invalid_mem = (void *)0xFFFFFFFFFFFFFF9B; // -100 for memset
#else
static void *invalid_mem = (void *)1;
#endif

static void
trigger_crash()
Expand Down
4 changes: 4 additions & 0 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ extern "C" {
#elif defined(__linux) || defined(__linux__)
# define SENTRY_PLATFORM_LINUX
# define SENTRY_PLATFORM_UNIX
#elif defined(_AIX)
/* IBM i PASE is also counted as AIX */
# define SENTRY_PLATFORM_AIX
# define SENTRY_PLATFORM_UNIX
#else
# error unsupported platform
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ elseif(LINUX OR ANDROID)
sentry_target_sources_cwd(sentry
modulefinder/sentry_modulefinder_linux.c
)
elseif(AIX)
sentry_target_sources_cwd(sentry
modulefinder/sentry_modulefinder_aix.c
)
endif()

# transport
Expand Down
109 changes: 109 additions & 0 deletions src/modulefinder/sentry_modulefinder_aix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "sentry_boot.h"

#include "sentry_core.h"
#include "sentry_string.h"
#include "sentry_sync.h"
#include "sentry_value.h"

#include <limits.h>
#include <stdio.h>

#define __XCOFF64__
#include <sys/ldr.h>
#include <xcoff.h>

/* library filename + ( + member file name + ) + NUL */
#define AIX_PRINTED_LIB_LEN ((PATH_MAX * 2) + 3)

static bool g_initialized = false;
static sentry_mutex_t g_mutex = SENTRY__MUTEX_INIT;
static sentry_value_t g_modules = { 0 };

static void
load_modules(void)
{
char buf[10000];
int r = loadquery(L_GETINFO, buf, 10000);
if (r == -1) {
return;
}
/* The loader info structures are also a linked list. */
struct ld_info *cur = (struct ld_info *)buf;
do {
sentry_value_t module = sentry_value_new_object();
sentry_value_set_by_key(
module, "type", sentry_value_new_string("xcoff"));

char *tb = (char *)cur->ldinfo_textorg; // text includes XCOFF image
sentry_value_set_by_key(
module, "image_addr", sentry__value_new_addr((uint64_t)tb));
// actually a 64-bit value on 64-bit AIX
uint64_t ts = (uint64_t)cur->ldinfo_textsize;
sentry_value_set_by_key(
module, "image_size", sentry_value_new_int32((uint32_t)ts));

/*
* Under AIX, there are no UUIDs for executables, but we can try to
* use some other fields as an ersatz substitute.
*/
FILHDR *xcoff_header = (FILHDR *)tb;
char timestamp[128];
snprintf(timestamp, 128, "%x", xcoff_header->f_timdat);
sentry_value_set_by_key(
module, "debug_id", sentry_value_new_string(timestamp));

/* library filename + ( + member + ) + NUL */
char libname[AIX_PRINTED_LIB_LEN];
char *file_part = cur->ldinfo_filename;
char *member_part = file_part + strlen(file_part) + 1;
/*
* This can't be a const char*, because it exists from
* a stack allocated buffer. Also append the member.
*
* XXX: See if we can't frob usla's memory ranges for
* const strings; but is quite difficult.
*/
if (member_part[0] == '\0') {
/* Not an archive, just copy the file name. */
snprintf(libname, AIX_PRINTED_LIB_LEN, "%s", file_part);
} else {
/* It's an archive with member. */
snprintf(
libname, AIX_PRINTED_LIB_LEN, "%s(%s)", file_part, member_part);
}
// XXX: This is not an absolute path because AIX doesn't provide
// it. It will have the member name for library archives.
sentry_value_set_by_key(
module, "code_file", sentry_value_new_string(libname));

sentry_value_append(g_modules, module);

cur = (struct ld_info *)((char *)cur + cur->ldinfo_next);
} while (cur->ldinfo_next != 0);
}

sentry_value_t
sentry_get_modules_list(void)
{
sentry__mutex_lock(&g_mutex);
if (!g_initialized) {
g_modules = sentry_value_new_list();
g_initialized = true;
load_modules();
sentry_value_freeze(g_modules);
}
sentry_value_t modules = g_modules;
sentry_value_incref(modules);
sentry__mutex_unlock(&g_mutex);
return modules;
}

void
sentry_clear_modulecache(void)
{
sentry__mutex_lock(&g_mutex);
sentry_value_decref(g_modules);
g_modules = sentry_value_new_null();
g_initialized = false;
sentry__mutex_unlock(&g_mutex);
}
32 changes: 29 additions & 3 deletions src/path/sentry_path_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
# include <mach-o/dyld.h>
#endif

#ifdef SENTRY_PLATFORM_AIX
# include <procinfo.h>
#endif

// only read this many bytes to memory ever
static const size_t MAX_READ_TO_BUFFER = 134217728;

Expand Down Expand Up @@ -50,7 +54,15 @@ sentry__filelock_try_lock(sentry_filelock_t *lock)
{
lock->is_locked = false;

int fd = open(lock->path->path, O_RDONLY | O_CREAT | O_TRUNC,
const int oflags =
#ifdef SENTRY_PLATFORM_AIX
// Under AIX, O_TRUNC can only be set if it can be written to, and
// flock (well, fcntl) will return EBADF if the fd is not read-write.
O_RDWR | O_CREAT | O_TRUNC;
#else
O_RDONLY | O_CREAT | O_TRUNC;
#endif
int fd = open(lock->path->path, oflags,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd < 0) {
return false;
Expand Down Expand Up @@ -130,6 +142,18 @@ sentry__path_current_exe(void)
}
buf[len] = 0;
return sentry__path_from_str(buf);
#elif defined(SENTRY_PLATFORM_AIX)
// You can't get the full path to the current executable; the best is
// either argv[0], or getting the name of the current executable, which
// doesn't even include a path. Let's go with that for now.
// (Actually, AIX may be able to under procfs, but it's System V style,
// not like Linux. And it's not available under PASE anyways.)
struct procentry64 proc;
pid_t pid = getpid();
if (getprocs64(&proc, sizeof(proc), NULL, 0, &pid, 1) < 1) {
return NULL;
}
return sentry__path_from_str(proc.pi_comm);
#endif
return NULL;
}
Expand Down Expand Up @@ -307,7 +331,7 @@ sentry__path_create_dir_all(const sentry_path_t *path)
#define _TRY_MAKE_DIR \
do { \
int mrv = mkdir(p, 0700); \
if (mrv != 0 && errno != EEXIST) { \
if (mrv != 0 && errno != EEXIST && errno != EINVAL) { \
rv = 1; \
goto done; \
} \
Expand Down Expand Up @@ -452,7 +476,9 @@ write_buffer_with_flags(
int fd = open(
path->path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
if (fd < 0) {
SENTRY_TRACEF("failed to open file \"%s\" for writing", path->path);
SENTRY_TRACEF(
"failed to open file \"%s\" for writing (errno %d, flags %x)",
path->path, errno, flags);
return 1;
}

Expand Down
8 changes: 8 additions & 0 deletions src/sentry_database.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ sentry__process_old_runs(const sentry_options_t *options, uint64_t last_crash)
sentry__filelock_free(lock);
continue;
}
// make sure we don't delete ourselves if the lock check fails
#ifdef SENTRY_PLATFORM_WINDOWS
if (wcscmp(options->run->run_path->path, run_dir->path) == 0) {
#else
if (strcmp(options->run->run_path->path, run_dir->path) == 0) {
#endif
continue;
}
sentry_pathiter_t *run_iter = sentry__path_iter_directory(run_dir);
const sentry_path_t *file;
while ((file = sentry__pathiter_next(run_iter)) != NULL) {
Expand Down
5 changes: 4 additions & 1 deletion src/sentry_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ sentry_options_new(void)
opts->auto_session_tracking = true;
opts->system_crash_reporter_enabled = false;
opts->symbolize_stacktraces =
#ifdef SENTRY_PLATFORM_ANDROID
// AIX doesn't have reliable debug IDs for server-side symbolication,
// and the diversity of Android makes it infeasible to have access to debug
// files.
#if defined(SENTRY_PLATFORM_ANDROID) || defined(SENTRY_PLATFORM_AIX)
true;
#else
false;
Expand Down
5 changes: 4 additions & 1 deletion src/sentry_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@ sentry__thread_setname(sentry_threadid_t thread_id, const char *thread_name)
return 1;
}
return pthread_setname_np(thread_name);
# else
# elif defined(SENTRY_PLATFORM_LINUX) /* and possibly others (like BSDs) */
return pthread_setname_np(thread_id, thread_name);
# else
/* XXX: AIX doesn't have it, but PASE does via ILE APIs. */
return 0;
# endif
}
#endif
Expand Down
16 changes: 16 additions & 0 deletions src/sentry_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,22 @@ typedef pthread_cond_t sentry_cond_t;
}
# endif
# define SENTRY__MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
# elif defined(SENTRY_PLATFORM_AIX)
// AIX lacks PTHREAD_RECURSIVE_MUTEX_INITIALIZER, though it does have at least
// PTHREAD_MUTEX_INITIALIZER. Unfortunately, it means you must call the mutex
// init function with an initialized mutexattrs set to recursive. This isn't
// workable due to all the mutexes just sitting around not initialized but
// immediately used. The fields are basically guesswork from what happens when
// you initialize the mutex "properly" but changing the bare minimum from a
// static initialization. (Don't ask me what these fields mean, the struct is
// opaquely defined as long[n] fields.)
# define SENTRY__MUTEX_INIT \
{ \
{ \
0, 0, 0, 0, /*_PTH_FLAGS_INIT64*/ 1, \
PTHREAD_MUTEX_RECURSIVE \
} \
}
# else
# define SENTRY__MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
# endif
Expand Down
34 changes: 31 additions & 3 deletions src/sentry_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,10 @@ sentry__dsn_new(const char *raw_dsn)
*tmp = 0;
dsn->path = url.path;
url.path = NULL;
dsn->is_valid = true;

if (dsn->public_key && dsn->host && dsn->path) {
dsn->is_valid = true;
}

exit:
sentry__url_cleanup(&url);
Expand Down Expand Up @@ -434,6 +437,29 @@ sentry__iso8601_to_msec(const char *iso)
tm.tm_sec = s;
#ifdef SENTRY_PLATFORM_WINDOWS
time_t time = _mkgmtime(&tm);
#elif defined(SENTRY_PLATFORM_AIX)
/*
* timegm is a GNU extension that AIX doesn't support. We'll have to fake
* it by setting TZ instead w/ mktime, then unsets it. Changes global env.
*/
time_t time;
char *tz_env;
tz_env = getenv("TZ");
if (tz_env) {
/* make a copy of it, since it'll change when we set it to UTC */
tz_env = strdup(tz_env);
}
setenv("TZ", "UTC", 1);
tzset();
time = mktime(&tm);
/* revert */
if (tz_env) {
setenv("TZ", tz_env, 1);
free(tz_env);
} else {
unsetenv("TZ");
}
tzset();
#else
time_t time = timegm(&tm);
#endif
Expand Down Expand Up @@ -476,7 +502,8 @@ sentry__strtod_c(const char *ptr, char **endptr)
{
#ifdef SENTRY_PLATFORM_WINDOWS
return _strtod_l(ptr, endptr, c_locale());
#elif defined(SENTRY_PLATFORM_ANDROID) || defined(SENTRY_PLATFORM_IOS)
#elif defined(SENTRY_PLATFORM_ANDROID) || defined(SENTRY_PLATFORM_IOS) \
|| defined(SENTRY_PLATFORM_AIX)
return strtod(ptr, endptr);
#else
return strtod_l(ptr, endptr, c_locale());
Expand All @@ -492,7 +519,8 @@ sentry__snprintf_c(char *buf, size_t buf_size, const char *fmt, ...)
int rv;
#ifdef SENTRY_PLATFORM_WINDOWS
rv = _vsnprintf_l(buf, buf_size, fmt, c_locale(), args);
#elif defined(SENTRY_PLATFORM_ANDROID) || defined(SENTRY_PLATFORM_IOS)
#elif defined(SENTRY_PLATFORM_ANDROID) || defined(SENTRY_PLATFORM_IOS) \
|| defined(SENTRY_PLATFORM_AIX)
rv = vsnprintf(buf, buf_size, fmt, args);
#elif defined(SENTRY_PLATFORM_DARWIN)
rv = vsnprintf_l(buf, buf_size, c_locale(), fmt, args);
Expand Down
Loading

0 comments on commit e76411c

Please sign in to comment.