Я смотрел на реализацию точек отмены в glibc / nptl и сравнивал ее с POSIX, и, если я не ошибаюсь, это совершенно неправильно. Используемая базовая модель:
int oldtype = LIBC_ASYNC_CANCEL(); /* switch to asynchronous cancellation mode */
int result = INLINE_SYSCALL(...);
LIBC_CANCEL_RESET(oldtype);
Согласно POSIX:
Побочные эффекты воздействия на запрос отмены во время приостановки во время вызова функции аналогичны побочным эффектам, которые могут наблюдаться в однопоточной программе, когда вызов функции прерывается сигналом и данная функция возвращает [EINTR]. Любые такие побочные эффекты возникают до вызова обработчиков отмены очистки.
Мое прочтение этого отрывка таково: если я позвоню open
, я могу ожидать, что либо будет отменено (вместе со всем моим потоком), прежде чем он не сможет открыть файл, или возвращает действительный дескриптор файла или значения -1 и errno
, но никогда не создает новый файловый дескриптор, а затем теряет его в пустоте. С другой стороны, реализация точек отмены в glibc / nptl, по-видимому, допускает состояние гонки, когда запрос отмены происходит сразу после возврата системного вызова, но до того, как произойдет LIBC_CANCEL_RESET
.
Я сумасшедший, или их реализация действительно сломана? И если да, то допускает ли POSIX такое неработающее поведение (которое, по-видимому, делает отмену полностью непригодным, если вы не откладываете ее вручную), или они просто нагло игнорируют POSIX?
Если это поведение действительно нарушено, как правильно его реализовать без такого состояния гонки?