Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::mutex::scoped_lock crashes on OSX
From: David Medine (dmedine_at_[hidden])
Date: 2015-12-16 13:34:53


On 12/16/2015 9:41 AM, Vicente J. Botet Escriba wrote:
> Le 15/12/2015 20:11, David Medine a écrit :
>> I am using boost in a python extension and it is having some problems
>> on OSX. Specifically, I use a mutex of type boost::mutex in both the
>> constructor and destructor methods. The constructor goes fine and the
>> destructor crashes. The code works perfectly well on both Windows and
>> Linux.
>>
>> When my class is building itself, it calls functions like this one a
>> bunch of times:
>>
>> void enter_headers_phase(bool phase_locked) {
>> if (phase_locked) {
>> boost::mutex::scoped_lock lock(phase_mut_);
>> headers_to_finish_++;
>> }
>> }
>>
>> where phase_mut_ is of type boost::mutex. When debugging in XCode, I
>> see nice looking members for phase_mut_ at this point in the program:
>>
>> phase_mut_ (boost::mutex)
>> m (pthread_mutex_t)
>> __sig (long) 1297437784 1297437784
>> __opaque char [56] ""
>>
>>
>> Later, when I am destroying, I make a nearly identical call as before:
>>
>> ...
>>
>> {
>> boost::mutex::scoped_lock lock(phase_mut_);
>> shutdown_ = true;
>> }
>>
>> ...
>>
>> but now, my phase_mut_ looks like it has an apparently empty _sig
>> member:
>>
>> phase_mut_ (boost::mutex)
>> m (pthread_mutex_t)
>> __sig (long)
>> __opaque (char [56]) ""
>>
>> When we go down the line of the mutex code in boost and finally
>> arrive at line 62 in boost/thread/pthread/mutex.hpp:
>>
>> ret = ::pthread_mutex_lock(m);
>>
>> I get a segmentation fault: EXC_BAD_ACCESS
>
> Hi,
>
> I need more context. Could you provide the declaration where
> phase_mut_ is in and the destructor of this class as well as where are
> you calling

Sure. The variable boost::mutex phase_mut_ is a private member of the
class 'recorder' as are several functions such as the one I quoted above,

private:

     // some other private members
     bool shutdown_;
     boost::uint32_t headers_to_finish_;
     boost::mutex phase_mut_;
     std::vector<thread_p> stream_threads_;

     void enter_headers_phase(bool phase_locked) {
         if (phase_locked) {
             boost::mutex::scoped_lock lock(phase_mut_);
             headers_to_finish_++;
         }
     }

     void leave_headers_phase(bool phase_locked) {
         if (phase_locked) {
             boost::mutex::scoped_lock lock(phase_mut_);
             headers_to_finish_--;
             lock.unlock();
             ready_for_streaming_.notify_all();
         }
     }
  // etc.

In the constructor, a thread is spawned that calls some of these
functions. Here is the constructor (abbreviated):

class recording {
public:
     recording(const std::string &filename, const
std::vector<lsl::stream_info> &streams, const std::vector<std::string>
&watchfor, bool collect_offsets=true) :
offsets_enabled_(collect_offsets), unsorted_(false), shutdown_(false),
streamid_(0), streaming_to_finish_(0), headers_to_finish_(0) {

     // blah blah blah

     // create a recording thread for each stream
     for (std::size_t k=0;k<streams.size();k++)
stream_threads_.push_back(thread_p(newboost::thread(&recording::record_from_streaminfo,this,streams[k],true)));
     // blah blah blah
}

This function record_from_streaminfo then callsenter_headers_phase with
the boolean true as the argument:

void record_from_streaminfo(lsl::stream_info src, bool phase_locked) {
     // blah blah blah

     // --- headers phase
     try {
         enter_headers_phase(phase_locked);
     }

     // blah blah blah

}

At this point the application is doing its recording and everything is
great.

>
> {
> boost::mutex::scoped_lock lock(phase_mut_);
> shutdown_ = true;
> }
>
> while on the destructor?

Here is the destructor (also abbreviated , but the mutex lock is the
very first thing that happens):

~recording() {
         try {
             // set the shutdown flag (from now on no more new streams)
             {
                 boost::mutex::scoped_lock lock(phase_mut_);
                 shutdown_ = true;
             }
     // etc. etc.
}

Thanks for taking a look at this. This is a terrible way to have to look
at code, so I really appreciate any time spent.

>
> Vicente
>>
>> It seems like this is becausem->_sig is now empty for some reason,
>> but I can not determine why (XCode's debugger won't let me 'watch'
>> this variable) but it should certainly be the case that it doesn't
>> get touched between the apparently successful constructor routines
>> and now.
>>
>> This all happens on OSX Yosemite. I am compiling my extension with
>> LLVM6.1 and I have gnu++0x as the C++ language dialect and libc++ as
>> the stdlib. I am linking statically to boost 1.57 which I built using
>> this command:
>>
>> sudo ./b2 -a cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++"
>> toolset=clang link=static link=shared threading=multi install
>> --prefix=/opt/local --layout-tagged
>>
>> THX!
>> -David
>>
>> _______________________________________________
>> Boost-users mailing list
>> Boost-users_at_[hidden]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>>
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net