I thought that we used this code everywhere, (I'd forgotten that we even provided a Delete() function for the API) but I was obviously wrong; both the Posix and Windows implementations /are/ different and rely on the OS to allocate IDs. On Posix reusing a pthread_key_t value after deleting it results in undefined behavior, but I suspect that in practice the storage in any other threads doesn't get deleted immediately, which is why Bruno's test worked.
The rationale section in the Linux pthread_key_delete() man-page describes how fraught with difficulty deleting the ID/key of a thread-private variable is in practice, and in Base most code doesn't delete the ID at all. Both the 3.15 and 7.0 branches contain 10 calls to epicsThreadPrivateCreate() and only 2 calls to epicsThreadPrivateDelete(), one of which is in the destructor for the C++ epicsThreadPrivate<T> template class (which only seems to be used in test programs), the other is here in CA's cacExitHandler().
I agree with Michael that removing the cacExitHandler() is probably the best solution. My previous commit already added a Release Note, the wording of which still applies, so it would make sense to modify this merge to finish off the necessary changes.
RTEMS and VxWorks both use the same basic implementation of epicsThreadPrivate variables for which the delete function does nothing:
> void epicsThreadPriv ateDelete (epicsThreadPri vateId id)
> {
> /* empty */
> }
I thought that we used this code everywhere, (I'd forgotten that we even provided a Delete() function for the API) but I was obviously wrong; both the Posix and Windows implementations /are/ different and rely on the OS to allocate IDs. On Posix reusing a pthread_key_t value after deleting it results in undefined behavior, but I suspect that in practice the storage in any other threads doesn't get deleted immediately, which is why Bruno's test worked.
The rationale section in the Linux pthread_ key_delete( ) man-page describes how fraught with difficulty deleting the ID/key of a thread-private variable is in practice, and in Base most code doesn't delete the ID at all. Both the 3.15 and 7.0 branches contain 10 calls to epicsThreadPriv ateCreate( ) and only 2 calls to epicsThreadPriv ateDelete( ), one of which is in the destructor for the C++ epicsThreadPriv ate<T> template class (which only seems to be used in test programs), the other is here in CA's cacExitHandler().
I agree with Michael that removing the cacExitHandler() is probably the best solution. My previous commit already added a Release Note, the wording of which still applies, so it would make sense to modify this merge to finish off the necessary changes.