Closed Bug 834945 Opened 11 years ago Closed 2 years ago

GC triggers a late DB write during shutdown

Categories

(Core :: XPCOM, defect)

defect
Not set
normal

Tracking

()

RESOLVED INCOMPLETE

People

(Reporter: vladan, Unassigned)

References

Details

Attachments

(1 file)

My shutdown profile shows GC triggering a flush of IndexedDB very late during shutdown. Are we not explicitly flushing IndexedDB at "profile-before-change"?

http://people.mozilla.com/~bgirard/cleopatra/#report=e2789c613c5c5f1a508ef8a6f0d7fb773b157c95

This is also evidence that skipping GCs at shutdown could cause data loss.
Where exactly do you see IndexedDB in here?

IndexedDB has code to flush at profile-before-change.  See IndexedDatabaseManager::Observe
    NtFlushBuffersFile
    NtFlushBuffersFile
    FlushFileBuffersImplementation
    winSync
    `anonymous namespace'::xSync(sqlite3_file *,int)
    walCheckpoint
    sqlite3WalCheckpoint
    sqlite3BtreeClose
    sqlite3LeaveMutexAndCloseZombie
    sqlite3Close
    sqlite3_close
    mozilla::storage::Connection::internalClose()
    mozilla::storage::Connection::~Connection()
    nsCOMPtr<nsIDirectoryServiceProvider>::`scalar deleting destructor'(unsigned int)
    nsTArray_Impl<nsRefPtr<mozilla::dom::CSSValue>,nsTArrayInfallibleAllocator>::DestructRange(unsigned int,unsigned int)
    nsTArray_Impl<nsRefPtr<mozilla::dom::HTMLCanvasElement>,nsTArrayInfallibleAllocator>::RemoveElementsAt(unsigned int,unsigned int)
    nsTArray_Impl<nsRefPtr<mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable>,nsTArrayInfallibleAllocator>::RemoveElement<mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable *,nsDefaultComparator<nsRefPtr<mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable>,mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable *> >(mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable * const &,nsDefaultComparator<nsRefPtr<mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable>,mozilla::dom::indexedDB::IndexedDatabaseManager::AsyncUsageRunnable *> const &)
    mozilla::storage::Service::unregisterConnection(mozilla::storage::Connection *)
    mozilla::storage::Connection::Release()
    mozilla::storage::Statement::~Statement()
    DoDeferredRelease<nsXPCWrappedJS *>
    Collect
    js::GC(JSRuntime *,js::JSGCInvocationKind,js::gcreason::Reason)
    js::DestroyContext(JSContext *,js::DestroyContextMode)
    JS_DestroyContext(JSContext *)
    mozJSComponentLoader::UnloadModules()
    mozJSComponentLoader::Observe(nsISupports *,char const *,wchar_t const *)
    mozilla::ShutdownXPCOM(nsIServiceManager *)
    ScopedXPCOMStartup::~ScopedXPCOMStartup()
    XREMain::XRE_main(int,char * * const,nsXREAppData const *)
    Startup::XRE_Main
    XRE_main
    do_main
    wmain
    __tmainCRTStartup
    BaseThreadInitThunk
    __RtlUserThreadStart
    _RtlUserThreadStart
    (root)
That looks like symbol coalescing, not anything real.

The mozstorage stuff used by IDB is never exposed to JS.
Any particular steps that can be used to reproduce this? If so I can try a debug build to see if the problem is just symbol coalescing, but this looks like a real late write from the NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID notification. Is this windows only? Has it triggered some late write report?
The "Late Writes" section of about:telemetry was empty after I restarted the browser. I filed bug 834938 for this. In general, I never see any late writes on my Windows machine
Looking a bit more, this *might* be safe, but I would still like to clear the statement reference earlier anyway. This is a sync connection (otherwise Connection::Close would leave it open), so sqlite3_close is "just" doing internal work (committing a log?) and should remain consistent.

Any tips on how to reproduce this?
I can reproduce this reliably on my work laptop it seems :S

New profile:

http://people.mozilla.com/~bgirard/cleopatra/#report=a45248030d47e8fbe42e76c1b465bd265994ea64
Summary: IndexedDB doesn't get explicitly flushed on shutdown? → GC triggers a late DB write during shutdown
I can send you my list of add-ons. I'll try to get the statement string or DB name tomorrow.
Component: DOM: IndexedDB → XPCOM
OK, vladan pointed out that this was only happening with PrivacyChoice TrackerBlock installed. I installed it on OS X and got an assertion failure on mozStorageService.cpp:829, which is almost certainly the same bug.
Assignee: nobody → respindola
Status: NEW → ASSIGNED
What is going on is:

* The addon keeps a reference to a connection to webappsstore.sqlite.
* On a debug build, we hit the assert about it not being closed.
* When NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID is sent, the reference goes away and GC closes the connection.
* webappsstore.sqlite is in Wal mode, and sqllite3_close will checkpoint. That is, it will copy data from the log(wal) to the btree.

So there is a bug in the addon, but this also shows a more general problem: In a release build, we want to do as little work during shutdown as possible. In particular, we don't want to close sync connections. This means we want them closed after the point we call exit(0), which is also the point where we will poison writes.

The net result is that will have to ignore writes coming from sqlite3WalCheckpoint (or maybe sqlite3_close itself). Since this is past the point were we currently poison writes, I propose that:

* For now, just add a comment to the source code pointing to this bug for well we try to move write poisoning before NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID.
* I will change the MOZ_ASSERT about connections being closed into something controlled by an environment variable (bug 704030) so that we can ping the addon author and ask them to fix their side.
Attachment #710870 - Flags: review?(vdjeric) → review+
As part of bug 916078, we should be able to force mozStorage to close everything during profile-before-change. Would this change anything for this bug?
(In reply to David Rajchenbach Teller [:Yoric] from comment #15)
> As part of bug 916078, we should be able to force mozStorage to close
> everything during profile-before-change. Would this change anything for this
> bug?

With the risk of breaking addons aside, yes it would fix this bug.

The bug assignee didn't login in Bugzilla in the last 7 months, so the assignee is being reset.

Assignee: respindola → nobody
Status: ASSIGNED → NEW

A patch adding a comment about this did land. It sounds like this bug is about eliminating late writes caused by some addon, so I'm not sure if that's still relevant. If somebody is working on late writes they can file a new bug.

Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → INCOMPLETE
Whiteboard: [leave open]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: