[webkit-reviews] review denied: [Bug 42843] Interrupt all DB operations when a worker is shutting down : [Attachment 62596] patch
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Mon Jul 26 14:51:15 PDT 2010
David Levin <levin at chromium.org> has denied Dumitru Daniliuc
<dumi at chromium.org>'s request for review:
Bug 42843: Interrupt all DB operations when a worker is shutting down
https://bugs.webkit.org/show_bug.cgi?id=42843
Attachment 62596: patch
https://bugs.webkit.org/attachment.cgi?id=62596&action=review
------- Additional Comments from David Levin <levin at chromium.org>
> Index: WebCore/ChangeLog
> ===================================================================
> --- WebCore/ChangeLog (revision 64062)
> +++ WebCore/ChangeLog (working copy)
> @@ -1,3 +1,35 @@
> +2010-07-26 Dumitru Daniliuc <dumi at chromium.org>
> +
> + Interrupt all DB operations when a worker is terminated.
> + https://bugs.webkit.org/show_bug.cgi?id=42843
> +
> + Tests: fast/workers/storage/interrupt-database-sync.html
> + fast/workers/storage/interrupt-database.html
> +
> + * platform/sql/SQLiteDatabase.cpp:
> + (WebCore::SQLiteDatabase::SQLiteDatabase):
> + (WebCore::SQLiteDatabase::interrupt):
> + * platform/sql/SQLiteDatabase.h:
> + (WebCore::SQLiteDatabase::isInterrupted):
> + (WebCore::SQLiteDatabase::databaseMutex):
> + * platform/sql/SQLiteStatement.cpp:
> + (WebCore::SQLiteStatement::prepare):
> + (WebCore::SQLiteStatement::step):
> + * storage/AbstractDatabase.cpp:
> + (WebCore::AbstractDatabase::interrupt):
> + * storage/AbstractDatabase.h:
> + * storage/DatabaseTracker.cpp:
> + (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
> + * storage/DatabaseTracker.h:
> + * storage/SQLStatement.cpp:
> + (WebCore::SQLStatement::execute):
> + * storage/SQLStatementSync.cpp:
> + (WebCore::SQLStatementSync::execute):
> + * storage/chromium/DatabaseTrackerChromium.cpp:
> + (WebCore::DatabaseTracker::interruptAllDatabasesForContext):
> + * workers/WorkerThread.cpp:
> + (WebCore::WorkerThread::stop):
In general, it is nice to have short comments here explaining what was done in
each place (see any of Darin Adler's commits for good examples).
> Index: WebCore/platform/sql/SQLiteDatabase.cpp
> +void SQLiteDatabase::interrupt()
> +{
> + if (!m_db)
> + return;
> +
> + while (!m_lockingMutex.tryLock())
> + sqlite3_interrupt(m_db);
How does this avoid doing the interrupt while with a database connection that
is closed on might be closed before this call returns. According to
http://www.sqlite.org/c3ref/interrupt.html, that is a dangerous thing to do.
> Index: WebCore/platform/sql/SQLiteDatabase.h
> + bool isInterrupted();
const?
> Index: WebCore/platform/sql/SQLiteStatement.cpp
> @@ -61,6 +61,11 @@ SQLiteStatement::~SQLiteStatement()
> int SQLiteStatement::prepare()
> {
> ASSERT(!m_isPrepared);
> +
> + MutexLocker databaseLock(m_database.databaseMutex());
> + if (m_database.isInterrupted())
> + return SQLITE_INTERRUPT;
For the naive folks (me), why do you need to take the lock in prepare() and
step() but no other methods?
> Index: WebCore/storage/DatabaseTracker.cpp
> + for (DatabaseSet::const_iterator dbSetIt =
databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt)
Style nit: need braces on this "for"
> + if ((*dbSetIt)->scriptExecutionContext() == context)
> + openDatabases.append(*dbSetIt);
> Index: WebCore/storage/chromium/DatabaseTrackerChromium.cpp
> ===================================================================
> --- WebCore/storage/chromium/DatabaseTrackerChromium.cpp (revision
64062)
> +++ WebCore/storage/chromium/DatabaseTrackerChromium.cpp (working copy)
> @@ -172,4 +172,30 @@ unsigned long long DatabaseTracker::getM
> return databaseSize + spaceAvailable;
> }
>
> +void DatabaseTracker::interruptAllDatabasesForContext(const
ScriptExecutionContext* context)
> +{
> + Vector<RefPtr<AbstractDatabase> > openDatabases;
> + {
> + MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard);
> +
> + if (m_openDatabaseMap) {
You could just return here.
> + DatabaseNameMap* nameMap =
m_openDatabaseMap->get(context->securityOrigin());
> + if (nameMap) {
You could just return here.
> + DatabaseNameMap::const_iterator dbNameMapEndIt =
nameMap->end();
> + for (DatabaseNameMap::const_iterator dbNameMapIt =
nameMap->begin(); dbNameMapIt != dbNameMapEndIt; ++dbNameMapIt) {
> + DatabaseSet* databaseSet = dbNameMapIt->second;
> + DatabaseSet::const_iterator dbSetEndIt =
databaseSet->end();
> + for (DatabaseSet::const_iterator dbSetIt =
databaseSet->begin(); dbSetIt != dbSetEndIt; ++dbSetIt)
Needs braces as before.
> + if ((*dbSetIt)->scriptExecutionContext() == context)
> + openDatabases.append(*dbSetIt);
> + }
> + }
> + }
> + }
> +
> + Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesEndIt =
openDatabases.end();
> + for (Vector<RefPtr<AbstractDatabase> >::const_iterator openDatabasesIt =
openDatabases.begin(); openDatabasesIt != openDatabasesEndIt;
++openDatabasesIt)
> + (*openDatabasesIt)->interrupt();
Why are there two copies of this code?
Given the small set of member variables used, it seems like it could easily be
a shared function if nothing else.
> Index: WebCore/workers/WorkerThread.cpp
> +#if ENABLE(DATABASE)
> #include "DatabaseTask.h"
> +#include "DatabaseTracker.h"
> +#endif
Ideally these #if includes should be placed after all other non-if'ed includes.
> Index: LayoutTests/fast/workers/storage/interrupt-database-sync.html
> +function runTest()
> +{
> + if (window.layoutTestController) {
> + layoutTestController.dumpAsText();
> + layoutTestController.waitUntilDone();
> + }
> +
> + worker = new Worker('resources/interrupt-database-sync.js');
> + worker.onmessage = function(event) {
> + if (event.data == "done")
> + finishTest();
> + else
> + log(event.data);
> + };
> +
> + setTimeout('terminateWorker()', 500);
Is it possible to avoid doing this as a timeout? The timeout has two downsides:
1. It may make the test take longer than necessary.
2. It may make the test flaky if somehow things take longer than expected on a
machine. (For example if running the test under valgrind.)
Here's some possible alternative.
1. Post a message from the worker after the db transactions have happened at
least once. Then do the terminate when you get this message back.
2. Put a specific value in the the db in the worker. Wait for that value to
appear before doing the terminate.
Ditto for the other test that uses a timeout for the same type of thing.
More information about the webkit-reviews
mailing list