Как гарантировать доставку сигнала от нескольких детей - PullRequest
2 голосов
/ 03 сентября 2010

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

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

Моя проблема в том, что программа завершается недетерминированным образом;сигналы не всегда доставляются.Обработчик сигнала не может быть проще:

void sig_child_ready (int sig)
{
    num_child_ready++;
}

num_child_ready объявлен как volatile sig_atomic_t.Я безуспешно пытался использовать sigprocmask в цикле, подобном следующему:

sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (num_child_ready < num_child)
{
    /* waiting for child signals here */
    sigsuspend (&oldmask);
}
sigprocmask (SIG_UNBLOCK, &mask, NULL);

Я не уверен, что делать дальше.Правильно ли я понимаю, что sigprocmask необходим для «постановки в очередь» сигналов, чтобы они обрабатывались один за другим?

Или рассмотрим этот гипотетический сценарий: родитель получает сигнал, выполняет свой обработчик, затем получает ДРУГОЙ идентичный сигнал.Обработчик сигнала вызывается рекурсивно?то есть будет ли он выполнять второй обработчик перед возвратом и завершением первого обработчика?

Я просто хочу убедиться, что все сигналы доставляются максимально синхронно.

1 Ответ

3 голосов
/ 03 сентября 2010

Нормальные сигналы не ставятся в очередь, и это, вероятно, является причиной вашей проблемы.

Если один сигнал поступит до того, как обработчик будет обработан для прошлого сигнала, они будут объединены, и вы мало что можете сделатьоб этом - вам, вероятно, лучше использовать какую-либо другую форму IPC для выполнения такого рода синхронизации.

Вы можете использовать «сигналы реального времени», которые действительно ставятся в очередь.Вы посылаете сигналы с sigqueue () и «получаете» их с помощью sigwaitinfo () или устанавливаете обработчик сигналов, устанавливающий флаг SA_SIGINFO в struct sigaction

...