Обработчик сигнала, обращающийся к структуре данных очереди (состояние гонки?)

В настоящее время я пишу небольшую оболочку на C++.

Задания и связанные с ними PID хранятся в очереди указателей заданий. (job *), Когда запускается новое задание, информация о нем добавляется в очередь. Так как несколько заданий могут обрабатываться одновременно и новые задания могут быть введены в консоли оболочки в любое время, у меня есть обработчик сигнала, который ожидает выполнения заданий, которые прекращаются.

Когда работа прекращается, мне нужно удалить ее информацию из активной очереди и переместить ее в мою очередь завершенных работ. Однако, возможно, что новое задание пользователя добавляется в очередь, когда другое задание останавливается.

В таком случае их insert операция очереди была бы приостановлена, и мой обработчик сигнала был бы вызван, который выполнил бы это pop операция.

Я пытаюсь понять, как я могу решить это потенциальное состояние гонки, поскольку я предполагаю, что коррупция может произойти во время этого процесса. Я не могу использовать мьютекс, поскольку возникнет взаимоблокировка, если прерванный родительский процесс использует очередь в то время.

Я вижу некоторую информацию о C++11 быть способным к атомарным операциям, как заявлено пользователем, наряду с информацией о тасклетах. Я не уверен, имеют ли они отношение к моему вопросу все же.

Интересно, что пример оболочки (MSH - http://code.google.com/p/mini-shell-msh/), которую я использую в качестве справки, по-видимому, не обрабатывает такие условия. Обработчик сигнала сразу же изменяет список заданий вместе с главной консолью. Возможно, здесь есть что-то, что я пропускаю?

Как всегда, все отзывы оценены.

2 ответа

Решение

У вас есть несколько способов избежать состояния гонки.

  • Использовать свободную (атомарную) очередь для указателей заданий;
  • использовать любой другой вид очереди, но защитить его sigprocmask (в коде не обработчика) и с надлежащим sa_mask значение в sigaction вызов;
  • вообще не используйте обработчик сигналов, используйте непереносимый системный вызов, который позволяет работать с сигналами синхронно: в Linux это возможно с signalfd, не уверен насчет других платформ.

Вам нужно отключить сигналы с sigprocmask() вокруг ваших критических разделов в коде не обработчика. Это аналогично драйверам устройств в ядре, отключающим прерывания в пользовательской половине драйвера при обновлении структур, используемых совместно с обработчиком прерываний.

Другие вопросы по тегам