2010-11-18 17 views
9

Szukałem implementacji punktów anulowania glibc/nptl i porównywania ich do POSIX-a, o ile się nie mylę, jest to całkowicie błędne. Podstawowy model stosowany:Jak powinny działać punkty kasowania POSIX?

int oldtype = LIBC_ASYNC_CANCEL(); /* switch to asynchronous cancellation mode */ 
int result = INLINE_SYSCALL(...); 
LIBC_CANCEL_RESET(oldtype); 

Według POSIX:

skutków ubocznych działający na żądanie unieważnienia, podczas gdy zawieszona w trakcie połączenia z funkcji są takie same, jak efekty uboczne, które można zobaczyć w programie jedno-gwintowym, gdy wywołanie funkcji jest przerywane sygnałem, a dana funkcja zwraca [EINTR]. Wszelkie takie efekty uboczne występują przed wywołaniem procedur usuwania anulowania.

Moje czytanie tego fragmentu jest to, że jeśli zadzwonię open, mogę oczekiwać, że albo aby anulowane (wraz z całym moim wątku), zanim nie otwiera plik, lub powrócić ważny deskryptor pliku lub wartość -1 i errno, ale nigdy, aby utworzyć nowy deskryptor pliku, a następnie utracić go w pustej przestrzeni. Z drugiej strony implementacja punktów anulowania przez glibc/nptl wydaje się dopuszczać warunki wyścigu, w których żądanie anulowania następuje tuż po powrocie systemu, ale przed LIBC_CANCEL_RESET ma miejsce.

Czy jestem szalony, czy też ich realizacja jest naprawdę zepsuta? A jeśli tak, to czy POSIX pozwala na takie zepsute zachowanie (które wydaje się sprawiać, że anulowanie jest całkowicie bezużyteczne, chyba że odłożysz je ręcznie), czy też są one rażąco ignorujące POSIX?

Jeśli to zachowanie jest w rzeczywistości uszkodzone, jaki jest prawidłowy sposób wdrożenia go bez takiego stanu wyścigu?

Odpowiedz

4

Czy nie jest to wyjaśnione w następnym akapicie normy:

Jednakże, jeśli wątek jest zawieszony na punkt anulowania i wydarzenie dla którym czeka występuje przed wniosek anulowania jest nieokreślony, to czy nie jest spełniony wniosek o anulowanie lub , czy żądanie anulowania pozostaje w toku, a wątek wznawia się normalnie.

Co oznacza, że ​​ten stan wyścigu jest całkowicie legalnym zachowaniem.

+3

Jak napisać solidny program o tak bezsensownym zachowaniu? Wygląda na to, że musisz albo zawijać każde wywołanie do "otwartego" (i innych punktów anulowania, które mogą alokować zasoby) z kodem, aby wyłączyć anulowanie, zachować anulowanie zawsze wyłączone i ręcznie wywoływać 'pthread_trycancel' okresowo, lub wymyślić jakiś sposób szukaj i uwolnij takie zasoby (dla deskryptorów plików możliwe jest przechodzenie przez wszystkie wartości, ale jest to dość niebezpieczne w przypadku aplikacji z gwintem bez niektórych zamków o dużym obciążeniu). –

+1

mmh, czytałem, że wątek nie może być jeszcze anulowany i powinien zostać anulowany w następnym punkcie anulowania (w takim przypadku, punkty anulowania wymagają obsługi systemu operacyjnego, i prawdopodobnie są zepsute w sposób opisany przez R .. większość systemów operacyjnych). – ninjalj

+0

@ninjaj: Myślę, że cmeerw może być poprawny. Fragment mówi, że jeśli (na przykład) wątek jest zawieszony czekając na powrót "otwartego", ale "otwarty" już zakończył wykonywanie swojej pracy, implementacja może umożliwić anulowanie lub pozostawienie go w toku. –