From 9a2b45caa81d8fb056802dfe3c25f214e808ffdf Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 19 Aug 2014 21:01:28 +0100 Subject: Use SafeStringStream instead of std::stringstream to try to fix random crashes on OS X. --- src/lib/safe_stringstream.h | 115 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/lib/safe_stringstream.h (limited to 'src/lib/safe_stringstream.h') diff --git a/src/lib/safe_stringstream.h b/src/lib/safe_stringstream.h new file mode 100644 index 000000000..e455de964 --- /dev/null +++ b/src/lib/safe_stringstream.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef DCPOMATIC_SAFE_STRINGSTREAM_H +#define DCPOMATIC_SAFE_STRINGSTREAM_H + +#include + +/* I've not been able to reproduce it, but there have been reports that DCP-o-matic crashes + * on OS X with two simultaneous backtraces that look like this: + * + * 0 libSystem.B.dylib 0x00007fff84ebe264 __numeric_load_locale + 125 + * 1 libSystem.B.dylib 0x00007fff84e2aac4 loadlocale + 323 + * 2 libstdc++.6.dylib 0x00007fff8976ba69 std::__convert_from_v(int* const&, char*, int, char const*, ...) + 199 + * 3 libstdc++.6.dylib 0x00007fff8974e99b std::ostreambuf_iterator > std::num_put > >::_M_insert_float(std::ostreambuf_iterator >, std::ios_base&, char, char, double) const + 199 + * 4 libstdc++.6.dylib 0x00007fff8974ebc0 std::num_put > +>::do_put(std::ostreambuf_iterator >, std::ios_base&, char, double) const + 28 + * 5 libstdc++.6.dylib 0x00007fff897566a2 std::ostream& std::ostream::_M_insert(double) + 178 + * 6 libdcpomatic.dylib 0x0000000100331e21 StringPrivate::Composition& StringPrivate::Composition::arg(float const&) + 33 + * + * in two different threads. I'm assuming that for some bizarre reason it is unsafe to use two separate stringstream + * objects in different threads on OS X. This is a hack to work around it. + */ + +class SafeStringStream +{ +public: + SafeStringStream () + {} + + SafeStringStream (std::string s) + : _stream (s) + {} + + template + std::ostream& operator<< (T val) + { + boost::mutex::scoped_lock lm (_mutex); + _stream << val; + return _stream; + } + + template + std::istream& operator>> (T& val) + { + boost::mutex::scoped_lock lm (_mutex); + _stream >> val; + return _stream; + } + + std::string str () const { + return _stream.str (); + } + + void str (std::string const & s) { + _stream.str (s); + } + + void imbue (std::locale const & loc) + { + boost::mutex::scoped_lock lm (_mutex); + _stream.imbue (loc); + } + + void width (int w) + { + _stream.width (w); + } + + void precision (int p) + { + _stream.precision (p); + } + + bool good () const + { + return _stream.good (); + } + + std::string getline () + { + boost::mutex::scoped_lock lm (_mutex); + std::string s; + std::getline (_stream, s); + return s; + } + + void setf (std::ios_base::fmtflags flags, std::ios_base::fmtflags mask) + { + _stream.setf (flags, mask); + } + +private: + static boost::mutex _mutex; + std::stringstream _stream; +}; + +#endif -- cgit v1.2.3