Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::mutex::scoped_lock crashes on OSX
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2015-12-16 16:58:16


Le 16/12/2015 19:34, David Medine a écrit :
>
>
> 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.
> }
>
I don't know from were the problem comes from, but you don't need to
lock on destruction as only one thread can call to the destructor.
However you need to joint the threads before deleting them.
> 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.
>
You are welcome.

Hoping this helps. If not I will need more code. You could send me
privately if you prefer.

Vicente


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