# HG changeset patch # User nickg # Date 1069411991 0 # Node ID 8a5eb4ab7bf55ade88bc8e4441d179293e5906f3 # Parent 0db10af9ebb784539250b4d53e289b0318ca8a64 * src/mqueue.cxx: Fix problem with mq_timedsend() and mq_timedreceive() timing out with zero timeouts even when there is room in the queue. * src/pthread.cxx (pthread_exit): Added code to disable cancellation requests during thread exit. This allows thread cleanup handlers to issue system calls when cleaning up thread resources. diff --git a/packages/compat/posix/current/ChangeLog b/packages/compat/posix/current/ChangeLog --- a/packages/compat/posix/current/ChangeLog +++ b/packages/compat/posix/current/ChangeLog @@ -1,3 +1,15 @@ +2003-11-19 Rickard Westman + + * src/mqueue.cxx: Fix problem with mq_timedsend() and + mq_timedreceive() timing out with zero timeouts even when there is + room in the queue. + +2003-11-17 Dan Jakubiec + + * src/pthread.cxx (pthread_exit): Added code to disable cancellation + requests during thread exit. This allows thread cleanup handlers + to issue system calls when cleaning up thread resources. + 2003-06-18 Jonathan Larmour * src/pthread.cxx (pthread_self_info): Just add some comments so diff --git a/packages/compat/posix/current/src/mqueue.cxx b/packages/compat/posix/current/src/mqueue.cxx --- a/packages/compat/posix/current/src/mqueue.cxx +++ b/packages/compat/posix/current/src/mqueue.cxx @@ -723,9 +723,18 @@ mq_timedsend( mqd_t mqdes, const char *m bool nonblocking = ((user->flags & O_NONBLOCK) == O_NONBLOCK); bool badtimespec = (abs_timeout->tv_nsec < 0) || (abs_timeout->tv_nsec > 999999999l); - err = tabent->mq->put( msg_ptr, msg_len, msg_prio, - !nonblocking && !badtimespec, - cyg_timespec_to_ticks(abs_timeout)); + cyg_tick_count abs_ticks = cyg_timespec_to_ticks(abs_timeout); + + // We should never time out if there is room in the queue. Simplest + // way to ensure this is to try the non-blocking put() first. + err = tabent->mq->put( msg_ptr, msg_len, msg_prio, false, abs_ticks ); + + // If the blocking variant would have blocked and that is what's wanted + if ( Cyg_Mqueue::WOULDBLOCK == err && !nonblocking && !badtimespec ) { + err = tabent->mq->put( msg_ptr, msg_len, msg_prio, true, + abs_ticks ); + } + switch (err) { case Cyg_Mqueue::INTR: @@ -808,9 +817,17 @@ mq_timedreceive( mqd_t mqdes, char *msg_ bool nonblocking = ((user->flags & O_NONBLOCK) == O_NONBLOCK); bool badtimespec = (abs_timeout->tv_nsec < 0) || (abs_timeout->tv_nsec > 999999999l); - err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, - !nonblocking && !badtimespec, - cyg_timespec_to_ticks(abs_timeout) ); + cyg_tick_count abs_ticks = cyg_timespec_to_ticks(abs_timeout); + + // We should never time out if there is something to read. Simplest + // way to ensure this is to try the non-blocking get() first. + err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, false, abs_ticks ); + + // If the blocking variant would have blocked and that is what's wanted + if ( Cyg_Mqueue::WOULDBLOCK == err && !nonblocking && !badtimespec ) { + err = tabent->mq->get( msg_ptr, &msg_len, msg_prio, true, abs_ticks ); + } + switch (err) { case Cyg_Mqueue::INTR: diff --git a/packages/compat/posix/current/src/pthread.cxx b/packages/compat/posix/current/src/pthread.cxx --- a/packages/compat/posix/current/src/pthread.cxx +++ b/packages/compat/posix/current/src/pthread.cxx @@ -699,6 +699,13 @@ externC void pthread_exit (void *retval) pthread_info *self = pthread_self_info(); + // Disable cancellation requests for this thread. If cleanup + // handlers exist, they will generally be issuing system calls + // to clean up resources. We want these system calls to run + // without cancelling, and we also want to prevent being + // re-cancelled. + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + // Call cancellation handlers. We eat up the buffers as we go in // case any of the routines calls pthread_exit() itself. while( self->cancelbuffer != NULL )