Skip to content

Commit

Permalink
Support Static Linking (#1261)
Browse files Browse the repository at this point in the history
* [C] Add aeron_symbol_table and use it to resovle internal symbols.  Encapsulate dlsym lookups.  Separate object and function pointers and correctly deal generic versions of each.  Remove multiple instances of warning ignores for -Wpendantic.

* [C] Fix windows compilation error.

* [C] Add unit test.  Break early on object resolution.

* [C] Switch to specifying length on symbol tables instead of using a NULL terminator.

* [C] Use struct to hold function pointer to avoid ignoring -Wpendantic.

* [C] Move function definition out of header.  Add missing prototype.

* [C] Use length when scanning function symbol tables.

* [C] Use strncmp to perform a bounded comparison.  Add additional bounded length check function.  Use typedef for generic function pointer.

* [C] Newline at end of file.
  • Loading branch information
mikeb01 authored Jan 23, 2022
1 parent f2f11fa commit 596a73b
Show file tree
Hide file tree
Showing 22 changed files with 641 additions and 307 deletions.
2 changes: 2 additions & 0 deletions aeron-client/src/main/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ set(SOURCE
util/aeron_parse_util.c
util/aeron_properties_util.c
util/aeron_strutil.c
util/aeron_symbol_table.c
uri/aeron_uri.c
aeron_agent.c
aeron_alloc.c
Expand Down Expand Up @@ -152,6 +153,7 @@ set(HEADERS
util/aeron_platform.h
util/aeron_properties_util.h
util/aeron_strutil.h
util/aeron_symbol_table.h
uri/aeron_uri.h
aeron_agent.h
aeron_alloc.h
Expand Down
79 changes: 31 additions & 48 deletions aeron-client/src/main/c/aeron_agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "util/aeron_error.h"
#include "util/aeron_dlopen.h"
#include "util/aeron_parse_util.h"
#include "util/aeron_symbol_table.h"
#include "aeron_agent.h"
#include "aeron_alloc.h"

Expand Down Expand Up @@ -282,6 +283,19 @@ aeron_idle_strategy_t aeron_idle_strategy_backoff =
aeron_idle_strategy_backoff_state_init_args
};

static const aeron_symbol_table_obj_t aeron_idle_strategy_table[] =
{
{ "sleeping", "aeron_idle_strategy_sleeping", &aeron_idle_strategy_sleeping },
{ "sleep-ns", "aeron_idle_strategy_sleeping", &aeron_idle_strategy_sleeping },
{ "yield", "aeron_idle_strategy_yielding", &aeron_idle_strategy_yielding },
{ "spin", "aeron_idle_strategy_busy_spinning", &aeron_idle_strategy_busy_spinning },
{ "noop", "aeron_idle_strategy_noop", &aeron_idle_strategy_noop },
{ "backoff", "aeron_idle_strategy_backoff", &aeron_idle_strategy_backoff },
};

static const size_t aeron_idle_strategy_table_length =
sizeof(aeron_idle_strategy_table) / sizeof (aeron_symbol_table_obj_t);

aeron_idle_strategy_func_t aeron_idle_strategy_load(
const char *idle_strategy_name,
void **idle_strategy_state,
Expand All @@ -292,74 +306,43 @@ aeron_idle_strategy_func_t aeron_idle_strategy_load(

if (NULL == idle_strategy_name || NULL == idle_strategy_state)
{
AERON_SET_ERR(EINVAL, "%s", "invalid idle strategy name or state");
AERON_SET_ERR(EINVAL, "%s", "invalid idle object name or state");
return NULL;
}

*idle_strategy_state = NULL;
aeron_idle_strategy_t *idle_strategy = aeron_symbol_table_obj_load(
aeron_idle_strategy_table, aeron_idle_strategy_table_length, idle_strategy_name, "idle strategy");

if (strncmp(idle_strategy_name, "sleep-ns", strlen("sleep-ns")) == 0 ||
strncmp(idle_strategy_name, "sleeping", strlen("sleeping")) == 0)
{
return aeron_idle_strategy_load("aeron_idle_strategy_sleeping", idle_strategy_state, env_var, init_args);
}
else if (strncmp(idle_strategy_name, "yield", strlen("yield")) == 0)
if (NULL == idle_strategy)
{
return aeron_idle_strategy_load("aeron_idle_strategy_yielding", idle_strategy_state, env_var, init_args);
}
else if (strncmp(idle_strategy_name, "spin", strlen("spin")) == 0)
{
return aeron_idle_strategy_load("aeron_idle_strategy_busy_spinning", idle_strategy_state, env_var, init_args);
}
else if (strncmp(idle_strategy_name, "noop", strlen("noop")) == 0)
{
return aeron_idle_strategy_load("aeron_idle_strategy_noop", idle_strategy_state, env_var, init_args);
}
else if (strncmp(idle_strategy_name, "backoff", strlen("backoff")) == 0)
{
return aeron_idle_strategy_load("aeron_idle_strategy_backoff", idle_strategy_state, env_var, init_args);
AERON_APPEND_ERR("%s", "");
return NULL;
}
else
{
char idle_func_name[AERON_MAX_PATH] = { 0 };
aeron_idle_strategy_t *idle_strategy = NULL;

snprintf(idle_func_name, sizeof(idle_func_name) - 1, "%s", idle_strategy_name);
if ((idle_strategy = (aeron_idle_strategy_t *)aeron_dlsym(RTLD_DEFAULT, idle_func_name)) == NULL)
{
AERON_SET_ERR(EINVAL, "could not find idle strategy %s: dlsym - %s", idle_func_name, aeron_dlerror());
return NULL;
}
idle_func = idle_strategy->idle;
aeron_idle_strategy_init_func_t idle_init_func = idle_strategy->init;

void *idle_state = NULL;
if (idle_init_func(&idle_state, env_var, init_args) < 0)
{
return NULL;
}
*idle_strategy_state = NULL;
idle_func = idle_strategy->idle;
aeron_idle_strategy_init_func_t idle_init_func = idle_strategy->init;

*idle_strategy_state = idle_state;
void *idle_state = NULL;
if (idle_init_func(&idle_state, env_var, init_args) < 0)
{
return NULL;
}

*idle_strategy_state = idle_state;

return idle_func;
}

aeron_agent_on_start_func_t aeron_agent_on_start_load(const char *name)
{
aeron_agent_on_start_func_t func = NULL;
#if defined(AERON_COMPILER_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
if ((func = (aeron_agent_on_start_func_t)aeron_dlsym(RTLD_DEFAULT, name)) == NULL)

if ((*(void **)(&func) = aeron_dlsym(RTLD_DEFAULT, name)) == NULL)
{
AERON_SET_ERR(EINVAL, "could not find agent on_start func %s: dlsym - %s", name, aeron_dlerror());
return NULL;
}
#if defined(AERON_COMPILER_GCC)
#pragma GCC diagnostic pop
#endif

return func;
}
Expand Down
2 changes: 2 additions & 0 deletions aeron-client/src/main/c/aeron_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ uint8_t aeron_semantic_version_minor(int32_t version);

uint8_t aeron_semantic_version_patch(int32_t version);

typedef void (*aeron_fptr_t)(void);

#endif //AERON_COMMON_H
19 changes: 19 additions & 0 deletions aeron-client/src/main/c/util/aeron_dlopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_lengt
return buffer;
}

const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length)
{
#if defined(AERON_COMPILER_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
void *addr = (void *)func;
#if defined(AERON_COMPILER_GCC)
#pragma GCC diagnostic pop
#endif
return aeron_dlinfo(addr, buffer, max_buffer_length);
}

#elif defined(AERON_COMPILER_MSVC)

#include "concurrent/aeron_counters_manager.h"
Expand Down Expand Up @@ -158,6 +171,12 @@ char *aeron_dlerror()
return messageBuffer;
}

const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length)
{
buffer[0] = '\0';
return buffer;
}

const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_length)
{
buffer[0] = '\0';
Expand Down
4 changes: 3 additions & 1 deletion aeron-client/src/main/c/util/aeron_dlopen.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
#define aeron_dlopen(x) dlopen(x, RTLD_LAZY | RTLD_GLOBAL)
#define aeron_dlerror dlerror

const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_length);
const char *aeron_dlinfo(const void *, char *buffer, size_t max_buffer_length);
const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length);

#elif defined(AERON_COMPILER_MSVC)

Expand All @@ -39,6 +40,7 @@ void *aeron_dlsym(void *module, const char *name);
void *aeron_dlopen(const char *filename);
char *aeron_dlerror();
const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_length);
const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length);

#else
#error Unsupported platform!
Expand Down
1 change: 1 addition & 0 deletions aeron-client/src/main/c/util/aeron_strutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,4 @@ int getopt(int argc, char *const argv[], const char *opt_string)
#endif

extern uint64_t aeron_fnv_64a_buf(uint8_t *buf, size_t len);
extern bool aeron_str_length(const char *str, size_t length_bound, size_t *length);
37 changes: 37 additions & 0 deletions aeron-client/src/main/c/util/aeron_strutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

void aeron_format_date(char *str, size_t count, int64_t timestamp);

Expand Down Expand Up @@ -78,4 +79,40 @@ AERON_EXPORT extern int optind;
int getopt(int argc, char *const argv[], const char *opt_string);
#endif

/**
* Checks that the string length is strictly less than the specified bound.
*
* @param str String to be compared.
* @param length_bound Limit to the length of the string being checked.
* @param length Out parameter for the actual length of the string (if non-null and less than length_bound).
* NULL values for this parameter are permitted. If str is NULL this value is unmodified. If
* the function returns false, the value is also unmodified.
* @return true if less than the specified bound, NULL is always true.
*/
inline bool aeron_str_length(const char *str, size_t length_bound, size_t *length)
{
if (NULL == str)
{
return true;
}

size_t i = 0;
bool result = false;
for (; i < length_bound; i++)
{
if ('\0' == str[i])
{
result = true;
break;
}
}

if (result && NULL != length)
{
*length = i;
}

return result;
}

#endif //AERON_STRUTIL_H
Loading

0 comments on commit 596a73b

Please sign in to comment.