I have this object that contains a thread. I want the fate of the object and the fate of the thread to be one in the same. So the constructor creates a thread (with pthread_create
) and the destructor performs actions to cause the thread to return in a reasonable amount of time and then joins the thread. This is working fine as long as I don't instantiate one of these objects with static storage duration. If I instantiate one of these objects at global or namespace or static class scope the program compiles fine (gcc 4.8.1) but immediately segfaults upon running. With print statements I have determined that the main thread doesn't even enter main() before the segfault. Any ideas?
Update: Also added a print statement to the first line of the constructor (so before pthread_create
is called), and not even that gets printed before the segfault BUT the constructor does use an initialization list so it is possible something there is causing it?
Here is the constructor:
worker::worker(size_t buffer_size):
m_head(nullptr),m_tail(nullptr),
m_buffer_A(operator new(buffer_size)),
m_buffer_B(operator new(buffer_size)),
m_next(m_buffer_A),
m_buffer_size(buffer_size),
m_pause_gate(true),
m_worker_thread([this]()->void{ thread_func(); }),
m_running(true)
{
print("this wont get printed b4 segfault");
scoped_lock lock(worker_lock);
m_worker_thread.start();
all_workers.push_back(this);
}
And destructor:
worker::~worker()
{
{
scoped_lock lock(worker_lock);
auto w=all_workers.begin();
while(w!=all_workers.end())
{
if(*w==this)
{
break;
}
++w;
}
all_workers.erase(w);
}
{
scoped_lock lock(m_lock);
m_running=false;
}
m_sem.release();
m_pause_gate.open();
m_worker_thread.join();
operator delete(m_buffer_A);
operator delete(m_buffer_B);
}
Update 2:
Okay I figured it out. My print function is atomic and likewise protects cout
with an extern namespace scope mutex defined elsewhere. I changed to just plain cout
and it printed at the beginning of the ctor. Apparently none of these static storage duration mutexes are getting initialized before things are trying to access them. So yeah it is probably Casey's answer.
I'm just not going to bother with complex objects and static storage duration. It's no big deal anyway.
main()
method. My suggestion would be to add more debug prints in constructor and destructor of your class – Bethelall_workers
appears to be another global object with static storage duration. Are you sure it is initialized before yourworker
object? – Moatsstderr
to log debug messages, or at least suffix the message with a\n
so the output stream will be flushed upon printing the message. – Prettypretty