~ubuntu-branches/ubuntu/raring/firebird2.5/raring-proposed

« back to all changes in this revision

Viewing changes to src/lock/lock.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2011-09-24 14:12:19 UTC
  • mfrom: (15.1.8 sid)
  • Revision ID: james.westby@ubuntu.com-20110924141219-pkxk7486f3d8ut9f
Tags: 2.5.1.26349-0~rc1.ds4-5
* Medium urgency for fixing a serious bug in testing

* Import a patch from upstream SVN fixing problems in poll() usage when
  process receives signals like SIGALRM.
  Closes: #642555 -- segfault in the remote interface when using alarm() in
  the client program

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
#endif
104
104
 
105
105
#ifdef DEV_BUILD
 
106
#define VALIDATE_LOCK_TABLE
 
107
#endif
 
108
 
 
109
#ifdef DEV_BUILD
106
110
#define ASSERT_ACQUIRED fb_assert(m_header->lhb_active_owner)
107
111
#if (defined HAVE_MMAP || defined WIN_NT)
108
112
#define LOCK_DEBUG_REMAP
109
113
#define DEBUG_REMAP_INTERVAL 5000
110
114
static ULONG debug_remap_count = 0;
111
115
#endif
112
 
#define CHECK(x)        { if (!(x)) bug_assert ("consistency check", __LINE__); }
 
116
#define CHECK(x)        do { if (!(x)) bug_assert ("consistency check", __LINE__); } while (false)
113
117
#else // DEV_BUILD
114
118
#define ASSERT_ACQUIRED
115
 
#define CHECK(x)
 
119
#define CHECK(x)        do { } while (false)
116
120
#endif // DEV_BUILD
117
121
 
118
122
#ifdef DEBUG_LM
176
180
        if (!g_lmMap->get(id, lockMgr))
177
181
        {
178
182
                lockMgr = new LockManager(id);
 
183
 
 
184
                if (g_lmMap->put(id, lockMgr))
 
185
                {
 
186
                        fb_assert(false);
 
187
                }
179
188
        }
180
189
 
181
190
        fb_assert(lockMgr);
182
191
 
 
192
        lockMgr->addRef();
183
193
        return lockMgr;
184
194
}
185
195
 
186
196
 
 
197
void LockManager::destroy(LockManager* lockMgr)
 
198
{
 
199
        if (lockMgr)
 
200
        {
 
201
                const Firebird::string id = lockMgr->m_dbId;
 
202
 
 
203
                Firebird::MutexLockGuard guard(g_mapMutex);
 
204
 
 
205
                if (!lockMgr->release())
 
206
                {
 
207
                        if (!g_lmMap->remove(id))
 
208
                        {
 
209
                                fb_assert(false);
 
210
                        }
 
211
                }
 
212
        }
 
213
}
 
214
 
 
215
 
187
216
LockManager::LockManager(const Firebird::string& id)
188
217
        : PID(getpid()),
189
218
          m_bugcheck(false),
203
232
        {
204
233
                Firebird::status_exception::raise(local_status);
205
234
        }
206
 
 
207
 
        Firebird::MutexLockGuard guard(g_mapMutex);
208
 
 
209
 
        if (g_lmMap->put(m_dbId, this))
210
 
        {
211
 
                fb_assert(false);
212
 
        }
213
235
}
214
236
 
215
237
 
271
293
                ISC_unmap_file(local_status, &m_extents[i].sh_data);
272
294
        }
273
295
#endif //USE_SHMEM_EXT
274
 
 
275
 
        Firebird::MutexLockGuard guard(g_mapMutex);
276
 
 
277
 
        if (!g_lmMap->remove(m_dbId))
278
 
        {
279
 
                fb_assert(false);
280
 
        }
281
296
}
282
297
 
283
298
 
814
829
}
815
830
 
816
831
 
 
832
bool LockManager::cancelWait(SRQ_PTR owner_offset)
 
833
{
 
834
/**************************************
 
835
 *
 
836
 *      c a n c e l W a i t
 
837
 *
 
838
 **************************************
 
839
 *
 
840
 * Functional description
 
841
 *      Wakeup waiting owner to make it check if wait should be cancelled.
 
842
 *      As this routine could be called asyncronous, take extra care and 
 
843
 *      don't trust the input params blindly.
 
844
 *
 
845
 **************************************/
 
846
        LOCK_TRACE(("cancelWait (%ld)\n", owner_offset));
 
847
 
 
848
        if (!owner_offset)
 
849
                return false;
 
850
 
 
851
        Firebird::MutexLockGuard guard(m_localMutex);
 
852
 
 
853
        acquire_shmem(DUMMY_OWNER);
 
854
        
 
855
        own* owner = (own*) SRQ_ABS_PTR(owner_offset);
 
856
        if (owner->own_type == type_own)
 
857
                post_wakeup(owner);
 
858
        
 
859
        release_shmem(DUMMY_OWNER);
 
860
        return true;
 
861
}
 
862
 
 
863
 
817
864
SLONG LockManager::queryData(SRQ_PTR parent_request, const USHORT series, const USHORT aggregate)
818
865
{
819
866
/**************************************
1081
1128
 
1082
1129
        // Check for shared memory state consistency
1083
1130
 
1084
 
        while (SRQ_EMPTY(m_header->lhb_processes))
 
1131
        if (SRQ_EMPTY(m_header->lhb_processes))
1085
1132
        {
1086
1133
                fb_assert(owner_offset == CREATE_OWNER);
1087
1134
                owner_offset = DUMMY_OWNER;
 
1135
        }
1088
1136
 
1089
 
                if (! m_sharedFileCreated)
 
1137
        while (SRQ_EMPTY(m_header->lhb_processes))
 
1138
        {
 
1139
                if (!m_sharedFileCreated)
1090
1140
                {
1091
1141
                        ISC_STATUS_ARRAY local_status;
1092
1142
 
1116
1166
        }
1117
1167
        fb_assert(!m_sharedFileCreated);
1118
1168
 
1119
 
 
1120
1169
        ++m_header->lhb_acquires;
1121
1170
        if (prior_active > 0) {
1122
1171
                ++m_header->lhb_acquire_blocks;
1182
1231
        // the lock mutex.  In that event, lets see if there is any unfinished work
1183
1232
        // left around that we need to finish up.
1184
1233
 
1185
 
        if (prior_active)
 
1234
        if (prior_active > 0)
1186
1235
        {
1187
1236
                post_history(his_active, owner_offset, prior_active, (SRQ_PTR) 0, false);
1188
1237
                shb* const recover = (shb*) SRQ_ABS_PTR(m_header->lhb_secondary);
1536
1585
}
1537
1586
 
1538
1587
 
1539
 
#ifdef DEV_BUILD
1540
1588
void LockManager::bug_assert(const TEXT* string, ULONG line)
1541
1589
{
1542
1590
/**************************************
1560
1608
 
1561
1609
        bug(NULL, buffer);      // Never returns
1562
1610
}
1563
 
#endif
1564
1611
 
1565
1612
 
1566
1613
void LockManager::bug(ISC_STATUS* status_vector, const TEXT* string)
1989
2036
                // If the blocking queue is not empty, then the owner still has some
1990
2037
                // AST's to process (or lock reposts).
1991
2038
                // hvlad: also lock maybe just granted to owner and blocked owners have no
1992
 
                // time to send blocking ATS
 
2039
                // time to send blocking AST
1993
2040
                // Remember this fact because they still might be part of a deadlock.
1994
2041
 
1995
2042
                if (owner->own_flags & (OWN_signaled | OWN_wakeup) || !SRQ_EMPTY((owner->own_blocks)) ||
3333
3380
}
3334
3381
 
3335
3382
 
3336
 
#ifdef VALIDATE_LOCK_TABLE
3337
 
 
3338
3383
const USHORT EXPECT_inuse = 0;
3339
3384
const USHORT EXPECT_freed = 1;
3340
3385
 
3501
3546
        const lbl* lock = (lbl*) SRQ_ABS_PTR(lock_ptr);
3502
3547
 
3503
3548
        if (freed == EXPECT_freed)
3504
 
                CHECK(lock->lbl_type == type_null)
 
3549
                CHECK(lock->lbl_type == type_null);
3505
3550
        else
3506
3551
                CHECK(lock->lbl_type == type_lbl);
3507
3552
 
3511
3556
 
3512
3557
        // The lbl_count's should never roll over to be negative
3513
3558
        for (ULONG i = 0; i < FB_NELEM(lock->lbl_counts); i++)
3514
 
                CHECK(!(lock->lbl_counts[i] & 0x8000))
 
3559
                CHECK(!(lock->lbl_counts[i] & 0x8000));
3515
3560
 
3516
3561
        // The count of pending locks should never roll over to be negative
3517
3562
        CHECK(!(lock->lbl_pending_lrq_count & 0x8000));
3582
3627
                direct_counts[request->lrq_state]++;
3583
3628
        }
3584
3629
 
3585
 
        if ((freed == EXPECT_inuse) && (lrq_ptr != 0))
 
3630
        if ((freed == EXPECT_inuse) && (lrq_ptr != 0)) {
3586
3631
                CHECK(found == 1);              // request is in lock's queue
3587
 
 
 
3632
        }
3588
3633
 
3589
3634
        if (freed == EXPECT_inuse)
3590
3635
        {
3625
3670
 
3626
3671
        CHECK(owner->own_type == type_own);
3627
3672
        if (freed == EXPECT_freed)
3628
 
                CHECK(owner->own_owner_type == 0)
 
3673
                CHECK(owner->own_owner_type == 0);
3629
3674
        else {
3630
3675
                CHECK(owner->own_owner_type <= 2);
3631
3676
        }
3774
3819
        const lrq* const request = (lrq*) SRQ_ABS_PTR(lrq_ptr);
3775
3820
 
3776
3821
        if (freed == EXPECT_freed)
3777
 
                CHECK(request->lrq_type == type_null)
 
3822
                CHECK(request->lrq_type == type_null);
3778
3823
        else
3779
3824
                CHECK(request->lrq_type == type_lrq);
3780
3825
 
3788
3833
        CHECK(!(request->lrq_flags & (LRQ_converting | LRQ_timed_out)));
3789
3834
 
3790
3835
        // Once a request is rejected, it CAN'T be pending any longer
3791
 
        if (request->lrq_flags & LRQ_rejected)
 
3836
        if (request->lrq_flags & LRQ_rejected) {
3792
3837
                CHECK(!(request->lrq_flags & LRQ_pending));
 
3838
        }
3793
3839
 
3794
3840
        // Can't both be scanned & marked for deadlock walk
3795
3841
        CHECK((request->lrq_flags & (LRQ_deadlock | LRQ_scanned)) != (LRQ_deadlock | LRQ_scanned));
3835
3881
        validate_history(secondary_header->shb_history);
3836
3882
}
3837
3883
 
3838
 
#endif  // VALIDATE_LOCK_TABLE
3839
 
 
3840
3884
 
3841
3885
USHORT LockManager::wait_for_request(thread_db* tdbb, lrq* request, SSHORT lck_wait)
3842
3886
{
4024
4068
                // See if we've waited beyond the lock timeout -
4025
4069
                // if so we mark our own request as rejected
4026
4070
 
4027
 
                if (lck_wait < 0 && lock_timeout <= current_time)
 
4071
                const bool cancelled = tdbb->checkCancelState(false); 
 
4072
 
 
4073
                if (cancelled || lck_wait < 0 && lock_timeout <= current_time)
4028
4074
                {
4029
4075
                        // We're going to reject our lock - it's the callers responsibility
4030
4076
                        // to do cleanup and make sure post_pending() is called to wakeup
4032
4078
                        request->lrq_flags |= LRQ_rejected;
4033
4079
                        request->lrq_flags &= ~LRQ_pending;
4034
4080
                        lock->lbl_pending_lrq_count--;
 
4081
                        
4035
4082
                        // and test - may be timeout due to missing process to deliver request
4036
4083
                        probe_processes();
4037
4084
                        release_shmem(owner_offset);