-
Philippe Gerum authored
This is a SMP race which seems to affect NPTL-based glibc releases (2.9 and 2.18 checked, other releases are likely concerned as well). The issue requires SMP setups to pop up, when --enable-async-cancel is mentioned on the Xenomai build configuration line. It was detected over the Mercury core, not checked on the Cobalt core. The work-around will fit both. The bug creates a situation where pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, ...) does not actually prevent subsequent asynchronous cancellation of the caller, in the following scenario: threadB has its cancellability set to PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_ASYNCHRONOUS on entry: threadA[CPU0]: pthread_cancel(threadB) (SIGCANCEL queued to threadB[CPU1]) threadB[CPU1]: pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) (SIGCANCEL delivered to threadB[CPU1]) <sigcancel_handler> if (cancel_type(threadB) == PTHREAD_CANCEL_ASYNCHRONOUS) __do_cancel(); ... As illustrated, the source of this issue is in glibc's SIGCANCEL handler, which only (re-)checks the cancellability TYPE prior to entering the thread deletion process on the target CPU, omitting the cancellability STATE from this check. High concurrency may therefore cause the target CPU to receive an asynchronous cancellation signal out of sync, which contradicts the current cancellability state of the recipient thread, due to the delayed signal propagation induced by SMP activities. Considering this, the cancellability state seems only safe for disabling the internal cancellation points, but can't be relied on for blocking asynchronous requests in SMP configurations. The work-around is to make sure to turn the cancellability type to PTHREAD_CANCEL_DEFERRED in addition to disabling cancellation with PTHREAD_CANCEL_DISABLE. Copperplate, and all Copperplate-based APIs are affected by the change.
75cc5dac