Обратный вызов POSIX AIO вызывается с одним и тем же (неправильным) сигвалом несколько раз

#c #posix #aio

Вопрос:

Я отправляю 100 запросов, используя aio_write. Я установил sigval (аргумент обратного вызова) для некоторого адреса с помощью request.aio_sigevent.sigev_value.sival_ptr = some_address; . У каждого запроса свой адрес. Обратный вызов должен записать некоторые данные по адресу.

Я ожидаю, что обратный вызов будет вызван 100 раз со 100 различными аргументами, которые я ему привел. Вместо этого обратный вызов вызывается 100 раз с одним и тем же аргументом каждый раз: аргументом для 100-го запроса. Я пробовал и с SIGEV_THREAD, и с SIGEV_SIGNAL с одинаковым результатом оба раза.

Фрагмент кода, в котором я отправляю запросы:

 for (int i = 0; i < num_requests; i  ) {
    struct aiocb request = build_request(/* snip */, amp;array[i]);
    aio_write(amp;request);
}
 

(где build_request просто создает a struct aiocb и записывает в поля aio, а также в aio_sigevent поля: sigev_notify , sigev_signo или sigev_notify_function , sigev_value.sival_ptr и.)

Почему это происходит?

Комментарии:

1. Из руководства aio_write : » Блок управления не должен изменяться во время выполнения операции записи».. В вашем случае переменная выходит за пределы области действия, как только заканчивается каждая итерация цикла. Таким образом, это неопределенное поведение как с точки зрения чистого языка Си, так и с точки зрения вызываемого API. Одним из решений является создание статического или динамического массива aiocb .

2. @kaylum Тьфу, этого бы хватило. Можете ли вы опубликовать это в качестве ответа? Это урок для меня, чтобы в следующий раз прочитать всю справочную страницу целиком… если бы только существовала технология для применения инвариантов, подобных этому 🙂

3. » если бы только существовала технология, позволяющая применять такие инварианты «. Это был бы язык ржавчины 🙂

4. Без сомнения! О, как бы я хотел им воспользоваться 🙂

Ответ №1:

Из руководства aio_write:

Блок управления не должен изменяться во время выполнения операции записи.

В вашем случае переменная выходит за пределы области действия, как только заканчивается каждая итерация цикла. Таким образом, это неопределенное поведение как с точки зрения чистого языка Си, так и с точки зрения вызываемого API. Одним из решений является создание статического или динамического массива aiocb.