Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
BroadcastCommunity.qnx.com will be offline from May 31 6:00pm until June 2 12:00AM for upcoming system upgrades. For more information please go to https://community.qnx.com/sf/discussion/do/listPosts/projects.bazaar/discussion.bazaar.topc28418
Forum Topic - pthread_sleepon_wait() bug: (1 Item)
   
pthread_sleepon_wait() bug  
Source reference: /coreos_pub/trunk/lib/c/qnx/sleepon.c

pthread_sleepon_wait() is documented as having the sleepon lock when it wakes up.  However, when pthread_sleepon_wait() 
is canceled, it does not have the sleepon lock such that thread cleanup code gets an error when attempting to release 
the sleepon lock.  In addition, if any code is executed in the cleanup code that attempts to modify items under the 
sleepon lock, they are unprotected...

While pthread_cond_wait() used to have this same problem back in QNX 6.2, since pthread_sleepon_wait() uses 
pthread_cond_wait(), which has since been fixed, it should not be having this problem.  However, there appears to be 
some cleanup code pushed around the pthread_cond_wait(), and it looks like this cleanup code may be unlocking the 
sleepon lock before it exits...

Obviously it is imperative that cleanup code that gets executed in the user's application due to pthread_sleepon_wait() 
being canceled have the sleepon lock.  The cleanup code cannot be taking action to cleanup items if it doesn't have the 
sleepon lock.  But, even in the simplest case, the cleanup code would be expected to at least unlock the sleepon lock.  
Take the example from the documentation:

int _sleepon(void *addr) {
    int ret;

    if((ret = pthread_sleepon_lock()) == EOK) {
        ret = pthread_sleepon_wait(addr);
        pthread_sleepon_unlock();
    }
    return ret;
}

If this same example were to be made thread safe, it would look more like:

void _cleanup(void) {
    pthread_sleepon_unlock();
}

int _sleepon(void *addr) {
    int ret;

    if((ret = pthread_sleepon_lock()) == EOK) {
        pthread_cleanup_push(_cleanup, NULL);
        ret = pthread_sleepon_wait(addr);
        pthread_cleanup_pop(1); // pthread_sleepon_unlock();
    }
    return ret;
}

However, if the pthread_sleepon_wait() is canceled, then the cleanup code will get an error (even though it isn't 
checking), trying to unlock the sleepon lock.