Если есть что-то более сложное, чем отладка многопоточного приложения, которое пытается описать саму ошибку.
- У меня есть два boost :: threads (приложение и отображение).
- Оба используют один и тот же asio :: io_service для выполнения своей работы.В потоке отображения есть std :: set типа window *, который я использую, чтобы обернуть управление окнами winapi.
- Я использую пользовательскую очередь сообщений для связи этих двух потоков.
- Одно из этих сообщений (прекратить) используется для уведомления потока вывода о том, что он не должен "публиковать" больше методов и что он должен вызывать thread_group.remove_thread и удалять себя.имеет переменную (состояние), которая отмечает состояние потока (запущен, приостановлен, завершен).
- Если он работает, он "отправляет" свой метод update (), который выполняет итерацию std :: set и вызывает метод обновления в каждом окне *, которое оно содержит.
- Если оно завершается, оноочищает std :: set, удаляет себя из группы thread_group и больше не публикует работы.
Проблема: время от времени при попытке закрыть приложение запускается метод обновления потокапосле того, как поток "завершен" и очищен std :: set.Затем метод обновления пытается выполнить итерацию std :: set и происходит SIGSEGV.Это происходит только 1 раз в 10 запусков приложения, и я с трудом пытаюсь угадать, что не так.
Я постараюсь опубликовать соответствующий код, если потребуется больше, я постараюсь добавитьit.
int main(int argc, char **argv)
{
boost::asio::io_service ios;
boost::asio::strand strand(ios);
boost::thread_group threads;
owl::system::pump pump;
application app(&threads, &strand, &pump);
owl::system::display display(&strand, &pump);
ios.run();
threads.join_all();
return 0;
}
...
void display::on_terminate()
{
close_all_windows();
}
...
void display::close_all_windows()
{
windows.move_first();
while (!windows.eof())
{
window* win = windows.value();
win->destroy();
delete win;
windows.move_next();
}
windows.clear();
check_no_window();
}
...
void display::on_update()
{
if (windows.size())
{
windows.move_first();
while (!windows.eof())
{
windows.value()->update();
windows.move_next(); // Here happens the SIGSEGV
}
}
}
Отображение класса наследует подсистему класса, которая управляет выполнением потока.Это соответствующий код, включающий выполнение on_update ()
void subsystem::do_update()
{
message* msg;
size_t message_count = messages.size();
for (size_t i=0; i<message_count; i++)
{
msg = messages[i];
process_message(msg);
strand->dispatch(strand->wrap(boost::bind(&message::deallocate, msg)));
}
switch (state)
{
case running:
{
on_update();
}
break;
case paused:
{
// Do not update. Just check the queue and sleep
sleep(10);
}
break;
case terminated:
{
do_terminate();
return;
}
break;
}
strand->post(strand->wrap(boost::bind(&subsystem::check_for_messages, this)));
}
void subsystem::check_for_messages()
{
messages.clear();
pump->get_messages(this, messages);
ios->post(boost::bind(&subsystem::do_update, this));
}
SIGSEGV происходит именно при попытке увеличить итератор std :: set.
Child process PID: 2272
Program received signal SIGSEGV, Segmentation fault.
In std::_Rb_tree_increment(std::_Rb_tree_node_base const*) ()
stl_tree.h:269