diff options
author | Adam Mitz <mitza@objectcomputing.com> | 2020-01-16 16:46:31 -0600 |
---|---|---|
committer | Adam Mitz <mitza@objectcomputing.com> | 2020-01-16 16:46:31 -0600 |
commit | 8161bcb366447083d67791bf14392a8882dc6659 (patch) | |
tree | a911a2f0a148a58c36288e51791cd8a9e0b17bcd /ACE/ace/OS_NS_Thread.cpp | |
parent | ecdb3766effde66789d83747f3ea5d93891cb1ef (diff) | |
download | ATCD-8161bcb366447083d67791bf14392a8882dc6659.tar.gz |
ACE_OS::rwlock_init - fixed bug when RW Lock is emulated and creating a condition variable fails
Diffstat (limited to 'ACE/ace/OS_NS_Thread.cpp')
-rw-r--r-- | ACE/ace/OS_NS_Thread.cpp | 134 |
1 files changed, 77 insertions, 57 deletions
diff --git a/ACE/ace/OS_NS_Thread.cpp b/ACE/ace/OS_NS_Thread.cpp index 5fbdf5add9b..6b64248a91b 100644 --- a/ACE/ace/OS_NS_Thread.cpp +++ b/ACE/ace/OS_NS_Thread.cpp @@ -3132,79 +3132,99 @@ ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params) #endif /* ! ACE_HAS_STHREADS && ! sun */ } +#if defined ACE_HAS_THREADS && defined ACE_LACKS_RWLOCK_T +namespace { +struct UniqueName { + explicit UniqueName (const void *addr) + { + ACE_OS::unique_name (addr, &this->buffer_[0], ACE_UNIQUE_NAME_LEN); + } + + operator const char * () const { return &this->buffer_[0]; } + + ACE_TCHAR buffer_[ACE_UNIQUE_NAME_LEN]; +}; + +enum RWLockCleanup {RWLC_CondAttr, RWLC_Lock, RWLC_Cond1, RWLC_Cond2}; + +struct RWLockCleaner { + RWLockCleaner (ACE_condattr_t &attr, ACE_rwlock_t *rw) + : state_ (RWLC_CondAttr) + , attr_ (attr) + , rw_ (rw) + {} + + ~RWLockCleaner () + { + ACE_Errno_Guard error (errno); + switch (this->state_) + { + case RWLC_Cond2: + ACE_OS::cond_destroy (&this->rw_->waiting_writers_); + // FALLTHROUGH + case RWLC_Cond1: + ACE_OS::cond_destroy (&this->rw_->waiting_readers_); + // FALLTHROUGH + case RWLC_Lock: + ACE_OS::mutex_destroy (&this->rw_->lock_); + // FALLTHROUGH + case RWLC_CondAttr: + ACE_OS::condattr_destroy (this->attr_); + } + } + + RWLockCleanup state_; + ACE_condattr_t &attr_; + ACE_rwlock_t *rw_; +}; +} +#endif + #if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T) int ACE_OS::rwlock_init (ACE_rwlock_t *rw, int type, - const ACE_TCHAR *name, + const ACE_TCHAR *, void *arg) { // ACE_OS_TRACE ("ACE_OS::rwlock_init"); # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T) // NT, POSIX, and VxWorks don't support this natively. - ACE_UNUSED_ARG (name); - int result = -1; - - // Since we cannot use the user specified name for all three - // objects, we will create three completely new names. - ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN]; - ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN]; - ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN]; - ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN]; - - ACE_OS::unique_name ((const void *) &rw->lock_, - name1, - ACE_UNIQUE_NAME_LEN); - ACE_OS::unique_name ((const void *) &rw->waiting_readers_, - name2, - ACE_UNIQUE_NAME_LEN); - ACE_OS::unique_name ((const void *) &rw->waiting_writers_, - name3, - ACE_UNIQUE_NAME_LEN); - ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_, - name4, - ACE_UNIQUE_NAME_LEN); ACE_condattr_t attributes; - if (ACE_OS::condattr_init (attributes, type) == 0) - { - if (ACE_OS::mutex_init (&rw->lock_, type, name1, - (ACE_mutexattr_t *) arg) == 0 - && ACE_OS::cond_init (&rw->waiting_readers_, - attributes, name2, arg) == 0 - && ACE_OS::cond_init (&rw->waiting_writers_, - attributes, name3, arg) == 0 - && ACE_OS::cond_init (&rw->waiting_important_writer_, - attributes, name4, arg) == 0) - { - // Success! - rw->ref_count_ = 0; - rw->num_waiting_writers_ = 0; - rw->num_waiting_readers_ = 0; - rw->important_writer_ = false; - result = 0; - } - ACE_OS::condattr_destroy (attributes); - } + if (ACE_OS::condattr_init (attributes, type) != 0) + return -1; - if (result == -1) - { - // Save/restore errno. - ACE_Errno_Guard error (errno); + RWLockCleaner cleanup (attributes, rw); - /* We're about to return -1 anyway, so - * no need to check return values of these clean-up calls: - */ - (void)ACE_OS::mutex_destroy (&rw->lock_); - (void)ACE_OS::cond_destroy (&rw->waiting_readers_); - (void)ACE_OS::cond_destroy (&rw->waiting_writers_); - (void)ACE_OS::cond_destroy (&rw->waiting_important_writer_); - } - return result; + if (ACE_OS::mutex_init (&rw->lock_, type, UniqueName (&rw->lock_), + (ACE_mutexattr_t *) arg) != 0) + return -1; + + cleanup.state_ = RWLC_Lock; + if (ACE_OS::cond_init (&rw->waiting_readers_, attributes, + UniqueName (&rw->waiting_readers_), arg) != 0) + return -1; + + cleanup.state_ = RWLC_Cond1; + if (ACE_OS::cond_init (&rw->waiting_writers_, attributes, + UniqueName (&rw->waiting_writers_), arg) != 0) + return -1; + + cleanup.state_ = RWLC_Cond2; + if (ACE_OS::cond_init (&rw->waiting_important_writer_, attributes, + UniqueName (&rw->waiting_important_writer_), arg) != 0) + return -1; + + cleanup.state_ = RWLC_CondAttr; + rw->ref_count_ = 0; + rw->num_waiting_writers_ = 0; + rw->num_waiting_readers_ = 0; + rw->important_writer_ = false; + return 0; # else ACE_UNUSED_ARG (rw); ACE_UNUSED_ARG (type); - ACE_UNUSED_ARG (name); ACE_UNUSED_ARG (arg); ACE_NOTSUP_RETURN (-1); # endif /* ACE_HAS_THREADS */ |