Skip to content

Commit

Permalink
Merge pull request #191 from boostorg/get-env-thread
Browse files Browse the repository at this point in the history
Make `getenv` thread-safe
  • Loading branch information
Flamefire authored Dec 20, 2024
2 parents 1423d15 + b9ff85d commit 9c673c0
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 5 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ jobs:
# Run test with both bash and powershell and watch for "Using std::cin" on bash but not on powershell
- name: Test
working-directory: build
run: ctest --output-on-failure -C ${{matrix.buildType}} --verbose
run: |
# The bash shell adds an incompatible PATH for MinGW: https://github.com/actions/runner-images/issues/11102
[[ "${{runner.os}}" != 'Windows' ]] || export PATH="/c/mingw64/bin:$PATH"
ctest --output-on-failure -C ${{matrix.buildType}} --verbose
- name: Test on PowerShell
working-directory: build
shell: powershell
Expand Down
6 changes: 5 additions & 1 deletion doc/changelog.dox
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (c) 2019-2023 Alexander Grund
// Copyright (c) 2019-2024 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
Expand All @@ -8,6 +8,10 @@

\section changelog Changelog

\subsection changelog_11_3_1 Nowide 11.3.1 (Boost 1.88)
- Fix redefinition of `_CRT_SECURE_NO_WARNINGS`
- Make `getenv` thread-safe

\subsection changelog_11_3_0 Nowide 11.3.0 (Boost 1.82)
- Add `convert_string` overload accepting a string
- Add `quoted` to output (quoted) paths (std::filesystem or boost::filesystem)
Expand Down
7 changes: 6 additions & 1 deletion include/boost/nowide/cstdlib.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ namespace nowide {
///
/// \brief UTF-8 aware getenv. Returns 0 if the variable is not set.
///
/// This function is not thread safe or reenterable as defined by the standard library
/// The string pointed to shall not be modified by the program.
/// This function is thread-safe as long as no other thread modifies the host environment.
/// However subsequent calls to this function might overwrite the string pointed to.
///
/// Warning: The returned pointer might only be valid for as long as the calling thread is alive.
/// So avoid passing it across thread boundaries.
///
BOOST_NOWIDE_DECL char* getenv(const char* key);

Expand Down
39 changes: 37 additions & 2 deletions src/cstdlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,46 @@ namespace nowide {
#include <vector>
#include <windows.h>

namespace {
// thread_local was broken on MinGW for all 32bit compiler releases prior to 11.x, see
// https://sourceforge.net/p/mingw-w64/bugs/527/
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562
// Using a non-trivial destructor causes program termination on thread exit.
#if defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__clang__) && (__GNUC__ < 11)
class stackstring_for_thread
{
union
{
boost::nowide::stackstring s_;
};

public:
stackstring_for_thread() : s_(){};
// Empty destructor so the union member (using a non-trivial destructor) does not get destroyed.
// This will leak memory if any is allocated by the stackstring for each terminated thread
// but as most values fit into the stack buffer this is rare and still better than a crash.
~stackstring_for_thread(){};
void convert(const wchar_t* begin, const wchar_t* end)
{
s_.convert(begin, end);
}

char* get()
{
return s_.get();
}
};
#else
using stackstring_for_thread = boost::nowide::stackstring;
#endif

} // namespace

namespace boost {
namespace nowide {
char* getenv(const char* key)
{
static stackstring value;
thread_local stackstring_for_thread value;

const wshort_stackstring name(key);

Expand All @@ -72,7 +107,7 @@ namespace nowide {
return 0;
ptr = &tmp[0];
}
value.convert(ptr);
value.convert(ptr, ptr + n);
return value.get();
}

Expand Down

0 comments on commit 9c673c0

Please sign in to comment.