Opened 9 years ago

Last modified 6 years ago

#8642 assigned Bugs

Global locale prevents from using Boost.Filesystem in global constructors and destructors

Reported by: Andrey Semashev Owned by: Beman Dawes
Milestone: To Be Determined Component: filesystem
Version: Boost 1.52.0 Severity: Problem
Keywords: Cc: daniel.kruegler@…, raad@…

Description

The problem appears in particular with Boost.Log. On program termination, Boost.Log may attempt to perform final log file rotation, which involves calling Boost.Filesystem routines (path construction, in particular). But Boost.Filesystem is not usable at this point because its global locale is already destroyed.

Boost.Filesystem should remain usable during global constructors and destructors. The global locale should either be embedded into the path object (preferred solution, IMHO) or the library should ensure its availability during these stages.

Attachments (2)

ticket8642.cpp (962 bytes ) - added by Andrey Semashev 8 years ago.
A testcase to reproduce the problem
ticket8642.valgrind.log (9.9 KB ) - added by Andrey Semashev 8 years ago.
Valgrind log

Download all attachments as: .zip

Change History (10)

comment:1 by Beman Dawes, 8 years ago

Status: newassigned

comment:2 by Beman Dawes, 8 years ago

Andy,

Could you please supply a simple test program that exhibits this problem?

Even if it is fixed now, I'd like to include something in the test suite that would detect any future regression.

Thanks,

--Beman

comment:3 by Andrey Semashev, 8 years ago

I don't have a code sample at hand; there were reports about Boost.Log (e.g. #9119) which I debugged to this root problem. I can try and write a self-contained test later this week.

comment:4 by daniel kruegler, 8 years ago

The following example should demonstrate the problem for every currently supported platform:

#include "boost/filesystem/path.hpp"

namespace fs = boost::filesystem;

template<class>
struct conv_char;

template<>
struct conv_char<wchar_t>
{
  typedef char value_type;
  static const value_type* file_name() { return "abcdefghijklmnopqrst.uvw"; }
};

template<>
struct conv_char<char>
{
  typedef wchar_t value_type;
  static const value_type* file_name() { return L"abcdefghijklmnopqrst.uvw"; }
};

typedef conv_char<fs::path::value_type> path_conv_char;

struct A
{
  A()
  {
  }

  ~A()
  {
    fs::path pa(path_conv_char::file_name());
  }

  static A& instance() 
  {
    static A result;
    return result;
  }

};

struct B 
{
  B() 
  { 
  }

  ~B() 
  { 
    A::instance(); 
    fs::path pb(path_conv_char::file_name());
  }
} b;

int main() 
{
}

The code ensures that we perform a code conversion in all cases and takes advantage of the life-cycle rules of objects with static storage duration. It gives me a seg fault using gcc and a similar crash for Visual Studio in the destructor of A. The example provokes that the locale produced by path_locale() (within path.cpp) is already destroyed when pa becomes constructed, because by path_locale() holds another function local static.

comment:5 by Daniel Krügler <daniel.kruegler@…>, 8 years ago

Cc: daniel.kruegler@… added

by Andrey Semashev, 8 years ago

Attachment: ticket8642.cpp added

A testcase to reproduce the problem

by Andrey Semashev, 8 years ago

Attachment: ticket8642.valgrind.log added

Valgrind log

comment:6 by Andrey Semashev, 8 years ago

I attached a test case which works similarly to Boost.Log. I also attached a valgrind log.

comment:7 by raad@…, 6 years ago

Cc: raad@… added

in reply to:  6 comment:8 by bchretien, 6 years ago

Replying to andysem:

I attached a test case which works similarly to Boost.Log. I also attached a valgrind log.

Note: to test the repro code from ticket8642.cpp, remember to set your locale (e.g. LANG=en_US ./ticket8642).

Note: See TracTickets for help on using tickets.