26
boost::posix_time::ptime parseDate(const std::string& format, const std::string& localDate)
{
    std::istringstream is(localDate);
    is.imbue(std::locale(is.getloc(), new boost::local_time::local_time_input_facet(format.c_str())));
    boost::posix_time::ptime pt;
    is >> pt;

    if (pt == boost::posix_time::ptime())
    {
        throw std::runtime_error("Parse error");
    }

    return pt;
}

This function should take a date and a format string and return boost::posix_time::ptime.

E.g.: 2012:06:14 02:50:58 and %Y:%m:%d %H:%M:%S.

However if I call it in a multithreaded program, sometimes the exception is thrown, although format and localDate are correct and parseable (I use the same date for every call). I found something about std::stringstream/std::locale thread issues but nothing up-to-date (I am using gcc 4.6.3 64bit).

Here someone has the same problem:

Testing over the last few days using Valgrind/drd, I have found many parts of my code that cause problems. For example, when calling some boost date time conversion functions, I hit std::locale(), which is not threadsafe.

Updated code that gives no problems:

boost::posix_time::ptime parseDate(const std::string& format, const std::string& localDate)
{
    std::istringstream is(localDate);
    auto* facet = new boost::local_time::local_time_input_facet(format.c_str());

    {
        boost::unique_lock<boost::mutex> lock(globalLocaleMutex);
        is.imbue(std::locale(is.getloc(), facet));
    }

    boost::posix_time::ptime pt;
    is >> pt;

    if (pt == boost::posix_time::ptime())
    {
        throw std::runtime_error("Parse error");
    }

    return pt;
}

But still: Why?

tauran
  • 7,986
  • 6
  • 41
  • 48
  • `throw std::runtime_error("Parse error");` – tauran Jun 20 '12 at 14:17
  • 1
    Are you using a multithreaded runtime library? VisualStudio for example has two - a single threaded and multi threaded. – Stephen Nutt Jun 20 '12 at 14:19
  • 10
    Based on your analysis, is your question really "Why is std::locale not threadsafe?" – Michael Kristofik Jun 20 '12 at 15:21
  • 1
    Yes! Is your question really why my question is why? – tauran Jun 20 '12 at 15:56
  • 4
    Sounds like a bug in libstdc++: std::locale constructor should not require any locking around it. May I suggest you report a bug report to GCC? See [link](http://gcc.gnu.org/bugs/) – vond Jun 20 '12 at 21:47
  • @bug report: So far I could not reproduce it without boost. Tried it with a `std::money_get` facet instead. Any ideas? – tauran Jun 21 '12 at 19:59
  • 1
    Have you tried stepping into the std::locale ctor and seeing what stuff is done there that might not be thread safe? – Martin Ba Jun 25 '12 at 13:20
  • How? I run the code in a parallel for loop with 10^6 iterations - and even then the problem does not always occour. – tauran Jun 29 '12 at 21:13
  • I have exactly the same problem in my code... it's really weird (with clang 3.5.0-svn217640-1~exp1 and gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) on ubuntu 14.04) – Nick Oct 30 '14 at 09:01

1 Answers1

1

I see there is a call to local_time. I am not sure if the underlying code calls localtime or localtime_r. If it calls localtime, then it is not thread safe. I believe that localtime uses a static variable when it returns the result.

dadinck
  • 1,118
  • 1
  • 7
  • 8