Skip to content

Add support for Haiku, a POSIX platform without thread naming and vasprintf #188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
56 changes: 44 additions & 12 deletions loguru.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@
#endif // LOGURU_STACKTRACES

#if LOGURU_PTHREADS
// for std::is_pointer<> to differentiate pthread_self() type variations
#include <type_traits>

#include <pthread.h>
#if defined(__FreeBSD__)
#include <pthread_np.h>
Expand Down Expand Up @@ -420,18 +423,27 @@ namespace loguru
LOGURU_PRINTF_LIKE(1, 0)
static Text vtextprintf(const char* format, va_list vlist)
{
#ifdef _WIN32
int bytes_needed = _vscprintf(format, vlist);
// Determine the required length of the string
int bytes_needed = 0;

// Calling vsnprintf is assumed to 'consume' the vlist, therefore we need a copy
// of the args to avoid corrupting the stack in the second call to vsnprintf.
va_list argcopy;
va_copy(argcopy, vlist);
bytes_needed = vsnprintf(NULL, 0, format, argcopy);
va_end(argcopy);
CHECK_F(bytes_needed >= 0, "Bad string format: '%s'", format);
char* buff = (char*)malloc(bytes_needed+1);
vsnprintf(buff, bytes_needed+1, format, vlist);
return Text(buff);
#else
char* buff = nullptr;
int result = vasprintf(&buff, format, vlist);
CHECK_F(result >= 0, "Bad string format: '" LOGURU_FMT(s) "'", format);

// Allocate the string's buffer
++bytes_needed; // Add space for null terminator
auto buff = static_cast<char*>(malloc(bytes_needed));
CHECK_F(buff != nullptr, "Out of memory");

// Construct the string and check the result
const auto written = vsnprintf(buff, bytes_needed, format, vlist);
CHECK_F(written <= bytes_needed, "Bad string format: '%s'", format);

return Text(buff);
#endif
}

Text textprintf(const char* format, ...)
Expand Down Expand Up @@ -578,6 +590,7 @@ namespace loguru
return Text(STRDUP(buff));
#else
// Not thread-safe.
(void)buff; // unused parameter
return Text(STRDUP(strerror(errno)));
#endif
}
Expand Down Expand Up @@ -626,6 +639,9 @@ namespace loguru
pthread_set_name_np(this_thread, main_thread_name);
#elif defined(__linux__) || defined(__sun)
pthread_setname_np(this_thread, main_thread_name);
#else
// platforms that we don't know how to set the name on
(void)this_thread; // unused
#endif
}
#endif // LOGURU_PTHREADS
Expand Down Expand Up @@ -1041,6 +1057,9 @@ namespace loguru
pthread_set_name_np(pthread_self(), name);
#elif defined(__linux__) || defined(__sun)
pthread_setname_np(pthread_self(), name);
#else
// Platforms that may not support setting a thread name
(void)name; // unused
#endif
#elif LOGURU_WINTHREADS
// Store thread name in a thread-local storage:
Expand Down Expand Up @@ -1068,7 +1087,12 @@ namespace loguru
// Ask the OS about the thread name.
// This is what we *want* to do on all platforms, but
// only some platforms support it (currently).
pthread_getname_np(pthread_self(), buffer, length);
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__sun)
pthread_getname_np(pthread_self(), buffer, length);
#else
// Other platforms that don't support thread names
buffer[0] = 0;
#endif
#elif LOGURU_WINTHREADS
snprintf(buffer, static_cast<size_t>(length), "%s", thread_name_buffer());
#else
Expand All @@ -1089,7 +1113,15 @@ namespace loguru
long thread_id;
(void)thr_self(&thread_id);
#elif LOGURU_PTHREADS
uint64_t thread_id = pthread_self();
const auto native_id = pthread_self();
// Warning, even within POSIX, return types and sizes vary:
// - Haku GCC returns a pthread_t*
// - ARM32 GCC returns an unsigned long long int
// So we bake the variations down to a common integer:
const auto pthread_self_is_pointer = std::is_pointer<decltype(native_id)>::value;
const auto thread_id = pthread_self_is_pointer
? reinterpret_cast<uintptr_t>((void*)native_id)
: static_cast<uintptr_t>(native_id);
#else
// This ID does not correllate to anything we can get from the OS,
// so this is the worst way to get the ID.
Expand Down