source: webkit/trunk/JavaScriptCore/wtf/MessageQueue.h@ 34960

Last change on this file since 34960 was 30811, checked in by [email protected], 17 years ago

JavaScriptCore:

Reviewed by Alexey and Mark Rowe

Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html

DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
removing particular items for Databases that were shutting down.

This filtering operation is not atomic, and therefore causes a race condition with the
MessageQueue waking up and reading from the message queue.

The end result was an attempt to dereference a null DatabaseTask. Timing-wise, this never
seemed to happen in a debug build, otherwise an assertion would've caught it. Replacing that
assertion with a crash in a release build is what revealed this bug.

  • wtf/MessageQueue.h: (WTF::::waitForMessage): Tweak the waiting logic to check the queue's empty state then go back to sleep if the queue was empty - checking m_killed each time it wakes up.

WebCore:

Reviewed by Alexey and Mark Rowe

Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html

DatabaseThread::unscheduleDatabaseTasks() manually filters through a MessageQueue,
removing particular items for Databases that were shutting down.

This filtering operation is not atomic, and therefore causes a race condition with the
database thread waking up and reading from the message queue.

The end result was an attempt to dereference a null DatabaseTask. Timing-wise, this never
seemed to happen in a debug build, otherwise an assertion would've caught it. Replacing that
assertion with a crash in a release build is what revealed this bug.

The fix for the above symptom was entirely in WTF::MessageQueue in JSCore. With this fix in
place, another crash popped up in the layout tests that was related to dereferencing a
deallocated object - simply because SQLTransaction had a raw pointer to it's Database object
when it needed to be a ref pointer.

  • storage/SQLTransaction.cpp: (WebCore::SQLTransaction::runCurrentStatement):
  • storage/SQLTransaction.h: Change m_database to be a RefPtr (WebCore::SQLTransaction::database):

LayoutTests:

Reviewed by Alexey + Mark Rowe

Fix for <rdar://problem/5778247> - Reproducible crash on storage/execute-sql-args.html

This test takes its best shot at handling two databases on a single database thread at once,
then having one of those databases go away completely (garbage collection and everything)

  • storage/multiple-databases-garbage-collection-expected.txt: Added.
  • storage/multiple-databases-garbage-collection.html: Added.
  • Property svn:eol-style set to native
File size: 3.7 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef MessageQueue_h
30#define MessageQueue_h
31
32#include <wtf/Assertions.h>
33#include <wtf/Deque.h>
34#include <wtf/Noncopyable.h>
35#include <wtf/Threading.h>
36
37namespace WTF {
38
39 template<typename DataType>
40 class MessageQueue : Noncopyable {
41 public:
42 MessageQueue() : m_killed(false) {}
43
44 void append(const DataType&);
45 void prepend(const DataType&);
46 bool waitForMessage(DataType&);
47 bool tryGetMessage(DataType&);
48 void kill();
49 bool killed() const;
50
51 private:
52 mutable Mutex m_mutex;
53 ThreadCondition m_condition;
54 Deque<DataType> m_queue;
55 bool m_killed;
56 };
57
58 template<typename DataType>
59 inline void MessageQueue<DataType>::append(const DataType& message)
60 {
61 MutexLocker lock(m_mutex);
62 m_queue.append(message);
63 m_condition.signal();
64 }
65
66 template<typename DataType>
67 inline void MessageQueue<DataType>::prepend(const DataType& message)
68 {
69 MutexLocker lock(m_mutex);
70 m_queue.prepend(message);
71 m_condition.signal();
72 }
73
74 template<typename DataType>
75 inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
76 {
77 MutexLocker lock(m_mutex);
78
79 while (!m_killed && m_queue.isEmpty())
80 m_condition.wait(m_mutex);
81
82 if (m_killed)
83 return false;
84
85 ASSERT(!m_queue.isEmpty());
86 result = m_queue.first();
87 m_queue.removeFirst();
88 return true;
89 }
90
91 template<typename DataType>
92 inline bool MessageQueue<DataType>::tryGetMessage(DataType& result)
93 {
94 MutexLocker lock(m_mutex);
95 if (m_killed)
96 return false;
97 if (m_queue.isEmpty())
98 return false;
99
100 result = m_queue.first();
101 m_queue.removeFirst();
102 return true;
103 }
104
105 template<typename DataType>
106 inline void MessageQueue<DataType>::kill()
107 {
108 MutexLocker lock(m_mutex);
109 m_killed = true;
110 m_condition.broadcast();
111 }
112
113 template<typename DataType>
114 inline bool MessageQueue<DataType>::killed() const
115 {
116 MutexLocker lock(m_mutex);
117 return m_killed;
118 }
119}
120
121using WTF::MessageQueue;
122
123#endif // MessageQueue_h
Note: See TracBrowser for help on using the repository browser.