Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIGBUS in future destructor #229

Closed
aaronalbers opened this issue Jan 15, 2019 · 11 comments
Closed

SIGBUS in future destructor #229

aaronalbers opened this issue Jan 15, 2019 · 11 comments

Comments

@aaronalbers
Copy link
Contributor

I am getting a SIGBUS when a stlab::future is destructed that I created via stlab::package and I am not sure why. It does not always happen making me think it is a race condition of some kind.

I am on release 4.1.0

Here is a minified stack trace (let me know if you want all the template parameters)

sighandler(int, siginfo_t*, void*)+2656 (69%)
/lib/arm-linux-gnueabihf/libc.so.6(+0x24fe0) [0xf6db3fe0]
__gnu_cxx::__exchange_and_add(int volatile*, int)+68 (41%)
__gnu_cxx::__exchange_and_add_dispatch(int*, int)+60 (42%)
_Sp_counted_base<>::_M_release()+60 (28%)
__shared_count<>::~__shared_count()+72 (56%)
__shared_ptr<>::~__shared_ptr()+52 (50%)
shared_ptr<>::~shared_ptr()+52 (50%)
stlab::future<>::detach() const::{lambda(auto:1)#1}::~detach()+44 (45%)
stlab::future<> stlab::shared_base<>::recover<>(stlab::future<>::detach() const::{lambda()#1}, auto stlab::shared_base<>::then<>(stlab::future<>::detach() const::{lambda(auto:1)#1}&&, stlab::future<>::detach() const::{lambda()#1}&&)::{lambda(auto:1)#1})::{lambda()#1}::~recover()+52 (50%)
stlab::task<>::model<>::~model()+44 (45%)
stlab::task<>::model<>::dtor(void*)+40 (45%)
stlab::task<>::operator=(stlab::task<>&&)+64 (35%)
stlab::shared<>::operator()()+268 (77%)
void stlab::packaged_task<>::operator()<>() const+100 (50%)
stlab::task<>::model<>::invoke(void*)+44 (50%)
stlab::task<>::operator()()+52 (54%)
stlab::task_system::run(unsigned int)+328 (74%)
stlab::task_system::task_system()::{lambda()#1}::operator()() const+60 (57%)
void _Bind_simple<>::_M_invoke<>(_Index_tuple<>)+48 (52%)
_Bind_simple<>::operator()()+40 (47%)
thread::_State_impl<>::_M_run()+44 (50%)
/usr/lib/arm-linux-gnueabihf/libstdc++.so.6(+0x8ca6a) [0xf6faaa6a]

I have been trying to track this down for 4 days now. I have not had any problems like this before with making my own futures. What could possibly cause something like this? I would try to add a minimal code example to reproduce the problem but that would be easier if I had a general idea of where to start.

@FelixPetriconi
Copy link
Member

Do you have an example program that can reproduce this?

@aaronalbers
Copy link
Contributor Author

Not currently. I am trying to produce a minimal example. As of right now I can only reproduce it in situ of some proprietary code. I was hoping you would have an idea on the class of issue this would be so I could have a starting point on making a reduction of the reproducible code.

@aaronalbers
Copy link
Contributor Author

In this example is it safe to call packagedTask multiple times? How about from different threads?

@FelixPetriconi
Copy link
Member

FelixPetriconi commented Jan 15, 2019

No. Futures are one use only. So you have to create for each call to package_task a new one. If you have multiple invocatons, you should considre to use a channel

@aaronalbers
Copy link
Contributor Author

I know that it won't resolve the future multiple times but is it safe to call it multiple times and have it be ignored?

@FelixPetriconi
Copy link
Member

It is not allowed to call package_task() multiple times, especially from multiple threads, because the call is not synchronized()

@aaronalbers
Copy link
Contributor Author

I don't know if this is the same crash that I ran into but I discovered this while trying to make a minimal example:

#include <iostream>

#define STLAB_TASK_SYSTEM 0 // portable

// built with stlab in same directory:
// clang++ -I. -std=c++14 main.cpp

// version 1.4.0 (develop)
#include <stlab/concurrency/default_executor.hpp>
#include <stlab/concurrency/utility.hpp>

#define WANT_SEG_FAULT

int main() {
   auto chain = stlab::make_ready_future(stlab::default_executor);
   
   size_t i = 0;
   
   while (true) {
      ++i;
      
      chain = chain.then([i]{
         auto p = stlab::package<void(size_t)>(stlab::default_executor, [](size_t i){
            std::cout << i << std::endl;
         });
         
         stlab::async(stlab::default_executor, std::bind(p.first, i)).detach();
         
         return p.second;
      });
      
      #ifdef WANT_SEG_FAULT
      if (i % 10000 == 0) chain = stlab::make_ready_future(stlab::default_executor);
      #else
      if (i % 1000 == 0) chain = stlab::make_ready_future(stlab::default_executor);
      #endif
      
   }
   
   return 0;
}

@FelixPetriconi
Copy link
Member

Thanks for the example. I can reproduce the problem, on Windows too.
I will start with the investigation.

@FelixPetriconi
Copy link
Member

My very first runs show that there is a stack overflow on Windows with the provided example. I will check later if I get the same results on my Mac.

FelixPetriconi added a commit to FelixPetriconi/libraries that referenced this issue Jan 27, 2019
FelixPetriconi added a commit that referenced this issue Jan 27, 2019
@FelixPetriconi
Copy link
Member

Fixed with #PR232

@FelixPetriconi
Copy link
Member

Fixed in 1.4.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants