From 00ac6d1d8e3e2dc9efe35aac8c65a6a0841f2376 Mon Sep 17 00:00:00 2001 From: Eric van Beurden Date: Fri, 9 Apr 2021 09:47:12 -0400 Subject: [PATCH 1/6] worked around Windows broken getenv() call. --- client/TracyProfiler.cpp | 45 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index de6b7817..2c657f10 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -225,6 +225,43 @@ static void InitFailure( const char* msg ) exit( 0 ); } +static const char* GetEnvVar(const char* name, char* buffer, size_t maxLen) +{ +#if defined _WIN32 || defined __CYGWIN__ + // unfortunately getenv() on Windows is just fundamentally broken. It caches the entire + // environment block once on startup, then never refreshes it again. If any environment + // strings are added or modified after startup of the CRT, those changes will not be + // seen by getenv(). This removes the possibility of an app using this SDK from + // programmatically setting any of the behaviour controlling envvars here. + // + // To work around this, we'll instead go directly to the Win32 environment strings APIs + // to get the current value. + DWORD count = GetEnvironmentVariableA(name, buffer, maxLen); + + if( count == 0 ) + return nullptr; + + if( count >= maxLen ) + { + char* buf = reinterpret_cast(_alloca(count + 1)); + count = GetEnvironmentVariableA(name, buf, count + 1); + memcpy(buffer, buf, maxLen); + buffer[maxLen - 1] = 0; + } + + return buffer; +#else + const char* value = getenv(name); + + if (value == nullptr) + return nullptr; + + strncpy(buffer, value, maxLen); + buffer[maxLen - 1] = 0; + return buffer; +#endif +} + static int64_t SetupHwTimer() { #if !defined TRACY_TIMER_QPC && !defined TRACY_TIMER_FALLBACK @@ -234,7 +271,8 @@ static int64_t SetupHwTimer() CpuId( regs, 0x80000007 ); if( !( regs[3] & ( 1 << 8 ) ) ) { - const char* noCheck = getenv( "TRACY_NO_INVARIANT_CHECK" ); + char buffer[32]; + const char* noCheck = GetEnvVar( "TRACY_NO_INVARIANT_CHECK", buffer, sizeof(buffer) / sizeof(buffer[0]) ); if( !noCheck || noCheck[0] != '1' ) { #if defined _WIN32 || defined __CYGWIN__ @@ -1225,15 +1263,16 @@ Profiler::Profiler() CalibrateDelay(); ReportTopology(); + char buffer[32]; #ifndef TRACY_NO_EXIT - const char* noExitEnv = getenv( "TRACY_NO_EXIT" ); + const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT", buffer, sizeof(buffer) / sizeof(buffer[0]) ); if( noExitEnv && noExitEnv[0] == '1' ) { m_noExit = true; } #endif - const char* userPort = getenv( "TRACY_PORT" ); + const char* userPort = GetEnvVar( "TRACY_PORT", buffer, sizeof(buffer) / sizeof(buffer[0]) ); if( userPort ) { m_userPort = atoi( userPort ); From fc142b4f9c4db03c7a8a6ec5d81e7acb6f4117ba Mon Sep 17 00:00:00 2001 From: Eric van Beurden Date: Fri, 9 Apr 2021 16:07:27 -0400 Subject: [PATCH 2/6] fixed a build break on AARCH64. --- client/TracyProfiler.cpp | 73 ++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 2c657f10..af49c97e 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -175,6 +175,42 @@ struct ThreadHandleWrapper }; #endif +static const char* GetEnvVar(const char* name, char* buffer, size_t maxLen) +{ +#if defined _WIN32 || defined __CYGWIN__ + // unfortunately getenv() on Windows is just fundamentally broken. It caches the entire + // environment block once on startup, then never refreshes it again. If any environment + // strings are added or modified after startup of the CRT, those changes will not be + // seen by getenv(). This removes the possibility of an app using this SDK from + // programmatically setting any of the behaviour controlling envvars here. + // + // To work around this, we'll instead go directly to the Win32 environment strings APIs + // to get the current value. + DWORD count = GetEnvironmentVariableA(name, buffer, maxLen); + + if( count == 0 ) + return nullptr; + + if( count >= maxLen ) + { + char* buf = reinterpret_cast(_alloca(count + 1)); + count = GetEnvironmentVariableA(name, buf, count + 1); + memcpy(buffer, buf, maxLen); + buffer[maxLen - 1] = 0; + } + + return buffer; +#else + const char* value = getenv(name); + + if (value == nullptr) + return nullptr; + + strncpy(buffer, value, maxLen); + buffer[maxLen - 1] = 0; + return buffer; +#endif +} #if defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 static inline void CpuId( uint32_t* regs, uint32_t leaf ) @@ -225,43 +261,6 @@ static void InitFailure( const char* msg ) exit( 0 ); } -static const char* GetEnvVar(const char* name, char* buffer, size_t maxLen) -{ -#if defined _WIN32 || defined __CYGWIN__ - // unfortunately getenv() on Windows is just fundamentally broken. It caches the entire - // environment block once on startup, then never refreshes it again. If any environment - // strings are added or modified after startup of the CRT, those changes will not be - // seen by getenv(). This removes the possibility of an app using this SDK from - // programmatically setting any of the behaviour controlling envvars here. - // - // To work around this, we'll instead go directly to the Win32 environment strings APIs - // to get the current value. - DWORD count = GetEnvironmentVariableA(name, buffer, maxLen); - - if( count == 0 ) - return nullptr; - - if( count >= maxLen ) - { - char* buf = reinterpret_cast(_alloca(count + 1)); - count = GetEnvironmentVariableA(name, buf, count + 1); - memcpy(buffer, buf, maxLen); - buffer[maxLen - 1] = 0; - } - - return buffer; -#else - const char* value = getenv(name); - - if (value == nullptr) - return nullptr; - - strncpy(buffer, value, maxLen); - buffer[maxLen - 1] = 0; - return buffer; -#endif -} - static int64_t SetupHwTimer() { #if !defined TRACY_TIMER_QPC && !defined TRACY_TIMER_FALLBACK From eac23cead252d39a59b35072d443e45a8f81b01f Mon Sep 17 00:00:00 2001 From: joshuakr Date: Fri, 9 Apr 2021 15:33:01 -0700 Subject: [PATCH 3/6] PR feedback --- client/TracyProfiler.cpp | 7 +++---- common/TracySocket.cpp | 5 +++-- common/TracySystem.cpp | 33 +++++++++++++++++++++++++++++++++ common/TracySystem.hpp | 2 ++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index af49c97e..41bdce71 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -270,8 +270,7 @@ static int64_t SetupHwTimer() CpuId( regs, 0x80000007 ); if( !( regs[3] & ( 1 << 8 ) ) ) { - char buffer[32]; - const char* noCheck = GetEnvVar( "TRACY_NO_INVARIANT_CHECK", buffer, sizeof(buffer) / sizeof(buffer[0]) ); + const char* noCheck = GetEnvVar( "TRACY_NO_INVARIANT_CHECK" ); if( !noCheck || noCheck[0] != '1' ) { #if defined _WIN32 || defined __CYGWIN__ @@ -1264,14 +1263,14 @@ Profiler::Profiler() char buffer[32]; #ifndef TRACY_NO_EXIT - const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT", buffer, sizeof(buffer) / sizeof(buffer[0]) ); + const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT" ); if( noExitEnv && noExitEnv[0] == '1' ) { m_noExit = true; } #endif - const char* userPort = GetEnvVar( "TRACY_PORT", buffer, sizeof(buffer) / sizeof(buffer[0]) ); + const char* userPort = GetEnvVar( "TRACY_PORT" ); if( userPort ) { m_userPort = atoi( userPort ); diff --git a/common/TracySocket.cpp b/common/TracySocket.cpp index f16569b0..1be7f051 100644 --- a/common/TracySocket.cpp +++ b/common/TracySocket.cpp @@ -8,6 +8,7 @@ #include "TracyAlloc.hpp" #include "TracySocket.hpp" +#include "TracySystem.hpp" #ifdef _WIN32 # ifndef NOMINMAX @@ -454,7 +455,7 @@ static int addrinfo_and_socket_for_family( uint16_t port, int ai_family, struct hints.ai_family = ai_family; hints.ai_socktype = SOCK_STREAM; #ifndef TRACY_ONLY_LOCALHOST - const char* onlyLocalhost = getenv( "TRACY_ONLY_LOCALHOST" ); + const char* onlyLocalhost = GetEnvVar( "TRACY_ONLY_LOCALHOST" ); if( !onlyLocalhost || onlyLocalhost[0] != '1' ) { hints.ai_flags = AI_PASSIVE; @@ -475,7 +476,7 @@ bool ListenSocket::Listen( uint16_t port, int backlog ) struct addrinfo* res = nullptr; #if !defined TRACY_ONLY_IPV4 && !defined TRACY_ONLY_LOCALHOST - const char* onlyIPv4 = getenv( "TRACY_ONLY_IPV4" ); + const char* onlyIPv4 = GetEnvVar( "TRACY_ONLY_IPV4" ); if( !onlyIPv4 || onlyIPv4[0] != '1' ) { m_sock = addrinfo_and_socket_for_family( port, AF_INET6, &res ); diff --git a/common/TracySystem.cpp b/common/TracySystem.cpp index 18b39dac..c893c92c 100644 --- a/common/TracySystem.cpp +++ b/common/TracySystem.cpp @@ -11,6 +11,7 @@ #endif #if defined _WIN32 || defined __CYGWIN__ # include +# include #else # include # include @@ -236,6 +237,38 @@ TRACY_API const char* GetThreadName( uint64_t id ) return buf; } +TRACY_API const char* GetEnvVar( const char* name ) +{ +#if defined _WIN32 || defined __CYGWIN__ + // unfortunately getenv() on Windows is just fundamentally broken. It caches the entire + // environment block once on startup, then never refreshes it again. If any environment + // strings are added or modified after startup of the CRT, those changes will not be + // seen by getenv(). This removes the possibility of an app using this SDK from + // programmatically setting any of the behaviour controlling envvars here. + // + // To work around this, we'll instead go directly to the Win32 environment strings APIs + // to get the current value. + static char buffer[1024]; + DWORD const kBufferSize = DWORD(sizeof(buffer) / sizeof(buffer[0])); + DWORD count = GetEnvironmentVariableA(name, buffer, kBufferSize); + + if( count == 0 ) + return nullptr; + + if( count >= kBufferSize ) + { + char* buf = reinterpret_cast(_alloca(count + 1)); + count = GetEnvironmentVariableA(name, buf, count + 1); + memcpy(buffer, buf, kBufferSize); + buffer[kBufferSize - 1] = 0; + } + + return buffer; +#else + return getenv(name); +#endif +} + } #ifdef __cplusplus diff --git a/common/TracySystem.hpp b/common/TracySystem.hpp index 2f539c2e..a032e606 100644 --- a/common/TracySystem.hpp +++ b/common/TracySystem.hpp @@ -25,6 +25,8 @@ static inline uint64_t GetThreadHandle() TRACY_API void SetThreadName( const char* name ); TRACY_API const char* GetThreadName( uint64_t id ); +TRACY_API const char* GetEnvVar(const char* name); + } #endif From 3fad55d7bc040c286b181d988f363e8505d7d0cd Mon Sep 17 00:00:00 2001 From: joshuakr Date: Fri, 9 Apr 2021 15:34:21 -0700 Subject: [PATCH 4/6] Missed one --- client/TracyProfiler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 41bdce71..2971ef60 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -1261,7 +1261,6 @@ Profiler::Profiler() CalibrateDelay(); ReportTopology(); - char buffer[32]; #ifndef TRACY_NO_EXIT const char* noExitEnv = GetEnvVar( "TRACY_NO_EXIT" ); if( noExitEnv && noExitEnv[0] == '1' ) From e845c234933ed40b476620976741d80e034e9a35 Mon Sep 17 00:00:00 2001 From: joshuakr Date: Fri, 9 Apr 2021 15:35:07 -0700 Subject: [PATCH 5/6] Removed duplicate function --- client/TracyProfiler.cpp | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 2971ef60..2ec79caa 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -175,43 +175,6 @@ struct ThreadHandleWrapper }; #endif -static const char* GetEnvVar(const char* name, char* buffer, size_t maxLen) -{ -#if defined _WIN32 || defined __CYGWIN__ - // unfortunately getenv() on Windows is just fundamentally broken. It caches the entire - // environment block once on startup, then never refreshes it again. If any environment - // strings are added or modified after startup of the CRT, those changes will not be - // seen by getenv(). This removes the possibility of an app using this SDK from - // programmatically setting any of the behaviour controlling envvars here. - // - // To work around this, we'll instead go directly to the Win32 environment strings APIs - // to get the current value. - DWORD count = GetEnvironmentVariableA(name, buffer, maxLen); - - if( count == 0 ) - return nullptr; - - if( count >= maxLen ) - { - char* buf = reinterpret_cast(_alloca(count + 1)); - count = GetEnvironmentVariableA(name, buf, count + 1); - memcpy(buffer, buf, maxLen); - buffer[maxLen - 1] = 0; - } - - return buffer; -#else - const char* value = getenv(name); - - if (value == nullptr) - return nullptr; - - strncpy(buffer, value, maxLen); - buffer[maxLen - 1] = 0; - return buffer; -#endif -} - #if defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 static inline void CpuId( uint32_t* regs, uint32_t leaf ) { @@ -223,6 +186,7 @@ static inline void CpuId( uint32_t* regs, uint32_t leaf ) #endif } + static void InitFailure( const char* msg ) { #if defined _WIN32 || defined __CYGWIN__ From fa942d18febde603a747118f7829ce86a5735159 Mon Sep 17 00:00:00 2001 From: joshuakr Date: Fri, 9 Apr 2021 15:35:44 -0700 Subject: [PATCH 6/6] Fix spacing --- client/TracyProfiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index 2ec79caa..039f493f 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -175,6 +175,7 @@ struct ThreadHandleWrapper }; #endif + #if defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 static inline void CpuId( uint32_t* regs, uint32_t leaf ) { @@ -186,7 +187,6 @@ static inline void CpuId( uint32_t* regs, uint32_t leaf ) #endif } - static void InitFailure( const char* msg ) { #if defined _WIN32 || defined __CYGWIN__