Changeset 64384 in webkit
- Timestamp:
- Jul 30, 2010 4:19:38 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r64357 r64384 1 2010-07-30 Dumitru Daniliuc <dumi@chromium.org> 2 3 Reviewed by Davin Levin. 4 5 Added a yield() function. 6 https://bugs.webkit.org/show_bug.cgi?id=42843 7 8 * JavaScriptCore.exp: 9 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: 10 * wtf/Threading.h: 11 * wtf/ThreadingPthreads.cpp: 12 (WTF::yield): 13 * wtf/ThreadingWin.cpp: 14 (WTF::yield): 15 * wtf/gtk/ThreadingGtk.cpp: 16 (WTF::yield): 17 * wtf/qt/ThreadingQt.cpp: 18 (WTF::yield): 19 1 20 2010-07-30 Rafael Antognolli <antognolli@profusion.mobi> 2 21 -
trunk/JavaScriptCore/JavaScriptCore.exp
r64334 r64384 368 368 __ZN3WTF5MutexC1Ev 369 369 __ZN3WTF5MutexD1Ev 370 __ZN3WTF5yieldEv 370 371 __ZN3WTF6strtodEPKcPPc 371 372 __ZN3WTF7CString11mutableDataEv -
trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
r64334 r64384 331 331 ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z 332 332 ?writable@PropertyDescriptor@JSC@@QBE_NXZ 333 ?yield@WTF@@YAXXZ 333 334 WTFLog 334 335 WTFLogVerbose -
trunk/JavaScriptCore/wtf/Threading.h
r64334 r64384 102 102 void detachThread(ThreadIdentifier); 103 103 104 void yield(); 104 105 105 106 void lockAtomicallyInitializedStaticMutex(); … … 113 114 using WTF::detachThread; 114 115 using WTF::waitForThreadCompletion; 116 using WTF::yield; 115 117 116 118 #endif // Threading_h -
trunk/JavaScriptCore/wtf/ThreadingPthreads.cpp
r64334 r64384 45 45 #if !COMPILER(MSVC) 46 46 #include <limits.h> 47 #include <sched.h> 47 48 #include <sys/time.h> 48 49 #endif … … 222 223 } 223 224 225 void yield() 226 { 227 sched_yield(); 228 } 229 224 230 ThreadIdentifier currentThread() 225 231 { -
trunk/JavaScriptCore/wtf/ThreadingWin.cpp
r64334 r64384 265 265 CloseHandle(threadHandle); 266 266 clearThreadHandleForIdentifier(threadID); 267 } 268 269 void yield() 270 { 271 ::Sleep(1); 267 272 } 268 273 -
trunk/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp
r64334 r64384 168 168 } 169 169 170 void yield() 171 { 172 g_thread_yield(); 173 } 174 170 175 Mutex::Mutex() 171 176 : m_mutex(g_mutex_new()) -
trunk/JavaScriptCore/wtf/qt/ThreadingQt.cpp
r64334 r64384 209 209 } 210 210 211 void yield() 212 { 213 QThread::yieldCurrentThread(); 214 } 215 211 216 Mutex::Mutex() 212 217 : m_mutex(new QMutex()) -
trunk/LayoutTests/ChangeLog
r64379 r64384 1 2010-07-30 Dumitru Daniliuc <dumi@chromium.org> 2 3 Reviewed by Davin Levin. 4 5 Test that terminating a worker interrupts all DB operations in that worker. 6 https://bugs.webkit.org/show_bug.cgi?id=42843 7 8 * fast/workers/storage/interrupt-database-expected.txt: Added. 9 * fast/workers/storage/interrupt-database-sync-expected.txt: Added. 10 * fast/workers/storage/interrupt-database-sync.html: Added. 11 * fast/workers/storage/interrupt-database.html: Added. 12 * fast/workers/storage/resources/interrupt-database-sync.js: Added. 13 * fast/workers/storage/resources/interrupt-database.js: Added. 14 (runTransaction): 15 1 16 2010-07-30 W. James MacLean <wjmaclean@google.com> 2 17 -
trunk/WebCore/ChangeLog
r64383 r64384 1 2010-07-30 Dumitru Daniliuc <dumi@chromium.org> 2 3 Reviewed by David Levin. 4 5 Interrupt all DB operations when the worker is terminating. 6 https://bugs.webkit.org/show_bug.cgi?id=42843 7 8 Tests: fast/workers/storage/interrupt-database-sync.html 9 fast/workers/storage/interrupt-database.html 10 11 * bindings/js/JSCustomVoidCallback.cpp: 12 (WebCore::JSCustomVoidCallback::~JSCustomVoidCallback): If the 13 destructor is called on the context thread, delete m_data directly 14 instead of posting a task to do that. We need to do that to make 15 sure that all JS objects are destroyed before 16 WorkerThreadShutdownFinishTask (in WorkerThread.cpp) calls 17 WorkerContext::clearScript(). 18 19 * bindings/scripts/CodeGeneratorJS.pm: Same change as above, for 20 all auto-generated callbacks. 21 22 * bindings/scripts/test/JS/JSTestCallback.cpp: 23 (WebCore::JSTestCallback::~JSTestCallback): Updated the 24 expectations for run-bindings-tests. 25 26 * platform/sql/SQLiteDatabase.cpp: Added the ability to interrupt 27 all DB operations in progress, unless the database was closed or 28 is being closed. Unlike sqlite3_interrupt(), 29 SQLiteDatabase::interrupt() is sticky: once it's called, trying to 30 run any statement on that database will fail with a 31 SQLITE_INTERRUPT error code. 32 (WebCore::SQLiteDatabase::SQLiteDatabase): 33 (WebCore::SQLiteDatabase::close): 34 (WebCore::SQLiteDatabase::interrupt): 35 (WebCore::SQLiteDatabase::isInterrupted): 36 37 * platform/sql/SQLiteDatabase.h: Added a mutex that can used by 38 SQLiteStatement to check if the database was interrupted. 39 (WebCore::SQLiteDatabase::databaseMutex): 40 41 * platform/sql/SQLiteStatement.cpp: Changed prepare() and step() 42 to check if the database was interrupted, before trying to prepare 43 or run the statement. The other methods don't need to hold on to 44 the DB lock while running, because they're fast, so we don't need 45 to interrupt them. 46 (WebCore::SQLiteStatement::prepare): 47 (WebCore::SQLiteStatement::step): 48 49 * storage/AbstractDatabase.cpp: Made SQLiteDatabase::interrupt() 50 and isInterrupted() visible to WebSQLDatabases classes. 51 (WebCore::AbstractDatabase::interrupt): 52 (WebCore::AbstractDatabase::isInterrupted): 53 * storage/AbstractDatabase.h: 54 55 * storage/DatabaseTracker.cpp: Added a method to interrupt all 56 databases in a given context. 57 (WebCore::DatabaseTracker::interruptAllDatabasesForContext): 58 * storage/DatabaseTracker.h: 59 60 * storage/SQLStatement.cpp: Changed the exception/error reported 61 when a statement is interrupted. 62 (WebCore::SQLStatement::execute): 63 * storage/SQLStatementSync.cpp: 64 (WebCore::SQLStatementSync::execute): 65 66 * storage/SQLTransaction.cpp: Changed the code to release the 67 callback objects as soon as they're not needed. 68 (WebCore::SQLTransaction::checkAndHandleClosedOrInterruptedDatabase): 69 Changed this method to not schedule the next transaction step when 70 the database is interrupted. 71 (WebCore::SQLTransaction::performNextStep): 72 (WebCore::SQLTransaction::performPendingCallback): 73 (WebCore::SQLTransaction::deliverTransactionCallback): 74 (WebCore::SQLTransaction::postflightAndCommit): 75 (WebCore::SQLTransaction::deliverTransactionErrorCallback): 76 (WebCore::SQLTransaction::cleanupAfterTransactionErrorCallback): 77 * storage/SQLTransaction.h: 78 79 * storage/chromium/DatabaseTrackerChromium.cpp: Added a method to 80 interrupt all databases in a given context. 81 (WebCore::DatabaseTracker::interruptAllDatabasesForContext): 82 83 * workers/WorkerThread.cpp: 84 (WebCore::WorkerThread::stop): Added a call to 85 DatabaseTracker::interruptAllDatabasesForContext(). 86 1 87 2010-07-30 Simon Fraser <simon.fraser@apple.com> 2 88 -
trunk/WebCore/bindings/js/JSCustomVoidCallback.cpp
r64334 r64384 49 49 JSCustomVoidCallback::~JSCustomVoidCallback() 50 50 { 51 m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data)); 51 if (m_scriptExecutionContext->isContextThread()) 52 delete m_data; 53 else 54 m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data)); 52 55 #ifndef NDEBUG 53 56 m_data = 0; -
trunk/WebCore/bindings/scripts/CodeGeneratorJS.pm
r64366 r64384 2169 2169 push(@implContent, "${className}::~${className}()\n"); 2170 2170 push(@implContent, "{\n"); 2171 push(@implContent, " m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));\n"); 2171 push(@implContent, " if (m_scriptExecutionContext->isContextThread())\n"); 2172 push(@implContent, " delete m_data;\n"); 2173 push(@implContent, " else\n"); 2174 push(@implContent, " m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data));\n"); 2172 2175 push(@implContent, "#ifndef NDEBUG\n"); 2173 2176 push(@implContent, " m_data = 0;\n"); -
trunk/WebCore/bindings/scripts/test/JS/JSTestCallback.cpp
r64334 r64384 44 44 JSTestCallback::~JSTestCallback() 45 45 { 46 m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data)); 46 if (m_scriptExecutionContext->isContextThread()) 47 delete m_data; 48 else 49 m_scriptExecutionContext->postTask(DeleteCallbackDataTask::create(m_data)); 47 50 #ifndef NDEBUG 48 51 m_data = 0; -
trunk/WebCore/platform/sql/SQLiteDatabase.cpp
r64334 r64384 32 32 #include "SQLiteFileSystem.h" 33 33 #include "SQLiteStatement.h" 34 35 34 #include <sqlite3.h> 35 #include <wtf/Threading.h> 36 36 37 37 namespace WebCore { … … 43 43 const int SQLResultSchema = SQLITE_SCHEMA; 44 44 const int SQLResultFull = SQLITE_FULL; 45 45 const int SQLResultInterrupt = SQLITE_INTERRUPT; 46 46 47 47 SQLiteDatabase::SQLiteDatabase() … … 51 51 , m_sharable(false) 52 52 , m_openingThread(0) 53 , m_interrupted(false) 53 54 { 54 55 } … … 86 87 // FIXME: This is being called on themain thread during JS GC. <rdar://problem/5739818> 87 88 // ASSERT(currentThread() == m_openingThread); 88 sqlite3_close(m_db); 89 m_db = 0; 89 sqlite3* db = m_db; 90 { 91 MutexLocker locker(m_databaseClosingMutex); 92 m_db = 0; 93 } 94 sqlite3_close(db); 90 95 } 91 96 92 97 m_openingThread = 0; 98 } 99 100 void SQLiteDatabase::interrupt() 101 { 102 m_interrupted = true; 103 while (!m_lockingMutex.tryLock()) { 104 MutexLocker locker(m_databaseClosingMutex); 105 if (!m_db) 106 return; 107 sqlite3_interrupt(m_db); 108 yield(); 109 } 110 111 m_lockingMutex.unlock(); 112 } 113 114 bool SQLiteDatabase::isInterrupted() 115 { 116 ASSERT(!m_lockingMutex.tryLock()); 117 return m_interrupted; 93 118 } 94 119 … … 398 423 } 399 424 400 void SQLiteDatabase::lock()401 {402 m_lockingMutex.lock();403 }404 405 void SQLiteDatabase::unlock()406 {407 m_lockingMutex.unlock();408 }409 410 425 bool SQLiteDatabase::isAutoCommitOn() const 411 426 { -
trunk/WebCore/platform/sql/SQLiteDatabase.h
r64334 r64384 49 49 extern const int SQLResultSchema; 50 50 extern const int SQLResultFull; 51 extern const int SQLResultInterrupt; 51 52 52 53 class SQLiteDatabase : public Noncopyable { … … 59 60 bool isOpen() const { return m_db; } 60 61 void close(); 62 void interrupt(); 63 bool isInterrupted(); 61 64 62 65 bool executeCommand(const String&); … … 106 109 void setAuthorizer(PassRefPtr<DatabaseAuthorizer>); 107 110 108 // (un)locks the database like a mutex 109 void lock(); 110 void unlock(); 111 Mutex& databaseMutex() { return m_lockingMutex; } 111 112 bool isAutoCommitOn() const; 112 113 … … 150 151 Mutex m_lockingMutex; 151 152 ThreadIdentifier m_openingThread; 152 153 154 Mutex m_databaseClosingMutex; 155 bool m_interrupted; 153 156 }; // class SQLiteDatabase 154 157 -
trunk/WebCore/platform/sql/SQLiteStatement.cpp
r64334 r64384 62 62 { 63 63 ASSERT(!m_isPrepared); 64 65 MutexLocker databaseLock(m_database.databaseMutex()); 66 if (m_database.isInterrupted()) 67 return SQLITE_INTERRUPT; 68 64 69 const void* tail = 0; 65 70 LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data()); … … 89 94 { 90 95 ASSERT(m_isPrepared); 96 97 MutexLocker databaseLock(m_database.databaseMutex()); 98 if (m_database.isInterrupted()) 99 return SQLITE_INTERRUPT; 100 91 101 if (!m_statement) 92 102 return SQLITE_OK; -
trunk/WebCore/storage/AbstractDatabase.cpp
r64334 r64384 475 475 } 476 476 477 void AbstractDatabase::interrupt() 478 { 479 m_sqliteDatabase.interrupt(); 480 } 481 482 bool AbstractDatabase::isInterrupted() 483 { 484 MutexLocker locker(m_sqliteDatabase.databaseMutex()); 485 return m_sqliteDatabase.isInterrupted(); 486 } 487 477 488 } // namespace WebCore 478 489 -
trunk/WebCore/storage/AbstractDatabase.h
r64334 r64384 69 69 unsigned long long maximumSize() const; 70 70 void incrementalVacuumIfNeeded(); 71 void interrupt(); 72 bool isInterrupted(); 71 73 72 74 // FIXME: move all version-related methods to a DatabaseVersionTracker class -
trunk/WebCore/storage/DatabaseTracker.cpp
r64334 r64384 236 236 } 237 237 238 void DatabaseTracker::interruptAllDatabasesForContext(const ScriptExecutionContext* context) 239 { 240 Vector<RefPtr<AbstractDatabase> > openDatabases; 241 { 242 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); 243 244 if (!m_openDatabaseMap) 245 return; 246 247 DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin()); 248 if (!nameMap) 249 return; 250 251 DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end(); 252 for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) { 253 DatabaseSet* databaseSet = dbNameMapIt->second; 254 DatabaseSet::const_iterator dbSetEndIt = databaseSet->end(); 255 for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) { 256 if ((*dbSetIt)->scriptExecutionContext() == context) 257 openDatabases.append(*dbSetIt); 258 } 259 } 260 } 261 262 Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt = openDatabases.end(); 263 for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt) 264 (*openDatabasesIt)->interrupt(); 265 } 266 238 267 String DatabaseTracker::originPath(SecurityOrigin* origin) const 239 268 { -
trunk/WebCore/storage/DatabaseTracker.h
r64334 r64384 78 78 unsigned long long getMaxSizeForDatabase(const AbstractDatabase*); 79 79 void databaseChanged(AbstractDatabase*); 80 81 void interruptAllDatabasesForContext(const ScriptExecutionContext*); 80 82 81 83 private: -
trunk/WebCore/storage/SQLStatement.cpp
r64334 r64384 79 79 if (result != SQLResultOk) { 80 80 LOG(StorageAPI, "Unable to verify correctness of statement %s - error %i (%s)", m_statement.ascii().data(), result, database->lastErrorMsg()); 81 m_error = SQLError::create( SQLError::SYNTAX_ERR, database->lastErrorMsg());81 m_error = SQLError::create(result == SQLResultInterrupt ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, database->lastErrorMsg()); 82 82 return false; 83 83 } … … 87 87 if (statement.bindParameterCount() != m_arguments.size()) { 88 88 LOG(StorageAPI, "Bind parameter count doesn't match number of question marks"); 89 m_error = SQLError::create( SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count");89 m_error = SQLError::create(db->isInterrupted() ? SQLError::DATABASE_ERR : SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count"); 90 90 return false; 91 91 } -
trunk/WebCore/storage/SQLStatementSync.cpp
r64334 r64384 62 62 int result = statement.prepare(); 63 63 if (result != SQLResultOk) { 64 ec = SQLException::SYNTAX_ERR;64 ec = (result == SQLResultInterrupt ? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR); 65 65 return 0; 66 66 } 67 67 68 68 if (statement.bindParameterCount() != m_arguments.size()) { 69 ec = SQLException::SYNTAX_ERR;69 ec = (db->isInterrupted()? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR); 70 70 return 0; 71 71 } -
trunk/WebCore/storage/SQLTransaction.cpp
r64334 r64384 147 147 #endif 148 148 149 void SQLTransaction::checkAndHandleClosed Database()150 { 151 if (m_database->opened() )149 void SQLTransaction::checkAndHandleClosedOrInterruptedDatabase() 150 { 151 if (m_database->opened() && !m_database->isInterrupted()) 152 152 return; 153 153 154 154 // If the database was stopped, don't do anything and cancel queued work 155 LOG(StorageAPI, "Database was stopped - cancelling work for this transaction");155 LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction"); 156 156 MutexLocker locker(m_statementMutex); 157 157 m_statementQueue.clear(); 158 158 m_nextStep = 0; 159 160 // Release the unneeded callbacks, to break reference cycles. 161 m_callback = 0; 162 m_successCallback = 0; 163 m_errorCallback = 0; 159 164 160 165 // The next steps should be executed only if we're on the DB thread. … … 184 189 m_nextStep == &SQLTransaction::cleanupAfterTransactionErrorCallback); 185 190 186 checkAndHandleClosed Database();191 checkAndHandleClosedOrInterruptedDatabase(); 187 192 188 193 if (m_nextStep) … … 203 208 m_nextStep == &SQLTransaction::deliverSuccessCallback); 204 209 205 checkAndHandleClosed Database();210 checkAndHandleClosedOrInterruptedDatabase(); 206 211 207 212 if (m_nextStep) … … 293 298 shouldDeliverErrorCallback = !m_callback->handleEvent(m_database->scriptExecutionContext(), this); 294 299 m_executeSqlAllowed = false; 300 m_callback = 0; 295 301 } 296 302 … … 460 466 // If the commit failed, the transaction will still be marked as "in progress" 461 467 if (m_sqliteTransaction->inProgress()) { 468 m_successCallback = 0; 462 469 m_transactionError = SQLError::create(SQLError::DATABASE_ERR, "failed to commit the transaction"); 463 470 handleTransactionError(false); … … 474 481 475 482 // Now release our unneeded callbacks, to break reference cycles. 476 m_callback = 0;477 483 m_errorCallback = 0; 478 484 … … 547 553 // Transaction Step 12 - If exists, invoke error callback with the last 548 554 // error to have occurred in this transaction. 549 if (m_errorCallback) 555 if (m_errorCallback) { 550 556 m_errorCallback->handleEvent(m_database->scriptExecutionContext(), m_transactionError.get()); 557 m_errorCallback = 0; 558 } 551 559 552 560 m_nextStep = &SQLTransaction::cleanupAfterTransactionErrorCallback; … … 580 588 m_nextStep = 0; 581 589 582 // Now release our callbacks, to break reference cycles.583 m_callback = 0;584 m_errorCallback = 0;585 586 590 // Now release the lock on this database 587 591 m_database->transactionCoordinator()->releaseLock(this); -
trunk/WebCore/storage/SQLTransaction.h
r64334 r64384 88 88 void enqueueStatement(PassRefPtr<SQLStatement>); 89 89 90 void checkAndHandleClosed Database();90 void checkAndHandleClosedOrInterruptedDatabase(); 91 91 92 92 void acquireLock(); -
trunk/WebCore/storage/chromium/DatabaseTrackerChromium.cpp
r64334 r64384 175 175 } 176 176 177 void DatabaseTracker::interruptAllDatabasesForContext(const ScriptExecutionContext* context) 178 { 179 Vector<RefPtr<AbstractDatabase> > openDatabases; 180 { 181 MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); 182 183 if (!m_openDatabaseMap) 184 return; 185 186 DatabaseNameMap* nameMap = m_openDatabaseMap->get(context->securityOrigin()); 187 if (!nameMap) 188 return; 189 190 DatabaseNameMap::const_iterator dbNameMapEndIt = nameMap->end(); 191 for (DatabaseNameMap::const_iterator dbNameMapIt = nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) { 192 DatabaseSet* databaseSet = dbNameMapIt->second; 193 DatabaseSet::const_iterator dbSetEndIt = databaseSet->end(); 194 for (DatabaseSet::const_iterator dbSetIt = databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt) { 195 if ((*dbSetIt)->scriptExecutionContext() == context) 196 openDatabases.append(*dbSetIt); 197 } 198 } 199 } 200 201 Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt = openDatabases.end(); 202 for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt = openDatabases.begin(); openDatabasesIt != openDatabasesEndIt; ++openDatabasesIt) 203 (*openDatabasesIt)->interrupt(); 204 } 205 177 206 } 178 207 -
trunk/WebCore/workers/WorkerThread.cpp
r64334 r64384 31 31 #include "WorkerThread.h" 32 32 33 #include "DatabaseTask.h"34 33 #include "DedicatedWorkerContext.h" 35 34 #include "KURL.h" … … 42 41 #include <wtf/Noncopyable.h> 43 42 43 #if ENABLE(DATABASE) 44 #include "DatabaseTask.h" 45 #include "DatabaseTracker.h" 46 #endif 47 44 48 namespace WebCore { 45 49 … … 226 230 m_workerContext->script()->forbidExecution(WorkerScriptController::TerminateRunningScript); 227 231 232 #if ENABLE(DATABASE) 233 DatabaseTracker::tracker().interruptAllDatabasesForContext(m_workerContext.get()); 234 #endif 235 228 236 // FIXME: Rudely killing the thread won't work when we allow nested workers, because they will try to post notifications of their destruction. 229 237 // This can likely use the same mechanism as used for databases above.
Note: See TracChangeset
for help on using the changeset viewer.