Есть метод вида:
ResultType Getter::get()
{
std::unique_lock<std::mutex> lock(mx);
Reader::readData();
}
Есть обработчик сигнала:
std::list<CommandMethod<>> Events;
std::mutex lock;
std::condition_variable check;
bool notified=false;
void EventDispatcherThread()
{
while (1)
{
std::unique_lock<std::mutex> locker(lock);
while (!notified)
check.wait(locker);
while (Events.size() > 0)
{
Events.front()();
Events.pop_front();
}
notified = false;
}
}
CommandMethod<> event(&controller,&Controller::EventHandler, SIGSYS);
int main(int argc, char *argv[])
{
std::thread sed_thread(&EventDispatcherThread);
sed_thread.detach();
std::signal(SIGSYS, [](int sig)->void {
std::unique_lock < std::mutex> lock(g_lock);
Events.push_back(event);
notified = true;
g_check.notify_all();
});
controller.main(argc, argv);
}
метод класса, который дергает обработчик:
Controller::EventHandler(int sig)
{
/*......*/
Getter::get();
}
метод класса, который исполняется в главном потоке.
Controller::main(int argc, char *argv[])
{
/*......*/
Getter::get();
}
Проблема в том, что сигнал срабатывющий, пока залочен мютекс в Getter::get()
главного потока в методе Controller::main(int argc, char *argv[])
прерывает его выполнение, и после обработки сигнала переходит к выполнению void EventDispatcherThread()
, который в свою очередь через Controller::EventHandler(int sig)
тоже вызывает Getter::get()
, тем самым возникает взаимоблокировка. Я понимаю, что обработчик сигнала может прервать контекст в любой момент, но как заставить его вернуться к прерванному контексту(в метод Controller::main(int argc, char *argv[])
) после обработки сигнала, а не после обработки EventDispatcherThread()
Спасибо avp, за правильную ссылку. g_check.notify_all();
не является безопасной для обработчика сигналов. Поток Controller::EventHandler(int sig)
пробуждался перед завершением обработчика сигнала, и ,видимо, по этой причине получал приоритет над основным потоком. Реализовал следующим образом:
sem_t sem;
void EventDispatcherThread()
{
while (1)
{
sem_wait(&sem);
controller.EventHandler(SIGSYS);
}
}
int main(int argc, char *argv[])
{
sem_init(&sem, 0, 10);
for (int i = 0; i < 10; ++i)
sem_wait(&sem);
std::thread sed_thread(&EventDispatcherThread);
sed_thread.detach();
std::signal(SIGSYS, [](int sig)->void {
sem_post(&sem);
});
controller.main(argc, argv);
}
Все оказалось намного проще.
Вопрос такого же плана: https://stackoverflow.com/questions/31117959/waking-up-thread-from-signal-handler
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Возможно ли как-то добавить классу QCameraViewfinder через сигнал или слот on_click как у обычной кнопки?
Мне нужен виджет секундомера, градусника, компаса и шкалы топливаВ одном стиле
предупреждение: 'ksp_ecology::_Mkrt' will be initialized after [-Wreorder] double _Mkrt;
Я знаю, что папки создаются через CreateDirectory и что через fstream можно создать например текстовик с заданным текстом, а как их совместить? То есть...