Bug 63391 - race condition (freeze) between "convert macros" and "connect DB" in FileOpen event
Summary: race condition (freeze) between "convert macros" and "connect DB" in FileOpen...
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Base (show other bugs)
Version:
(earliest affected)
3.6.3.2 release
Hardware: All All
: medium major
Assignee: Lionel Elie Mamane
URL: https://gerrit.libreoffice.org/3310
Whiteboard: target:4.1.0
Keywords:
Depends on:
Blocks:
 
Reported: 2013-04-10 16:44 UTC by Lionel Elie Mamane
Modified: 2013-04-29 13:02 UTC (History)
1 user (show)

See Also:
Crash report or crash signature:


Attachments
More detailed notes, with full backtraces, etc (20.33 KB, text/plain)
2013-04-10 16:44 UTC, Lionel Elie Mamane
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Lionel Elie Mamane 2013-04-10 16:44:03 UTC
Created attachment 77759 [details]
More detailed notes, with full backtraces, etc

Let foo.odb be a database file that has this macro on "Open Document" event:


Sub Foo
	Dim DBDocUI as Object
	DBDocUI = ThisDatabaseDocument.currentController
	if not DBDocUI.isConnected then
		DBDocUI.connect
	end if
End Sub

The effect of this macro is to immediately connect to the database when opening foo.odb, instead of lazily waiting for something to need it. (I do that because I then use "stmt.executeUpdate()" to set various DBMS-specific settings automatically.)

Sometimes, but now always, when opening this file, LibreOffice freezes.

I've tracked it down to a race condition between two actions:

 1) the asynchronous treatment of "OnFirstControllerConnected" in dbaui::OApplicationController,
    which tries to get dbaui::OApplicationController's mutex

 2) the StarBasic macro calling dbaui::OApplicationController::connect
    which needs to display a dialog (to get username and password),
    and thus puts that dialog in the main thread's event queue
    and waits for it ... with dbaui::OApplicationController's mutex held

Now, if "1)" is before "2)" in the event queue of the the main thread,
*but* "1)" is executed *after* "2)" has taken the lock, there is a deadlock.

Fix:

 1) Make OnFirstControllerConnected synchronous.
    Make sure (by taking mutex in dbaui::OApplicationController::attachFrame, its ancestor in the call graph)
    that nothing else will happen with the OApplicationController as long as it is not finished.
    ---> it does not need to take mutex itself anymore

 2) Change dbaui::OApplicationController::ensureConnection to do the user prompting
    WITHOUT HOLDING the mutex, and use the mutex "only" to protect actually assigning
    the connection to m_xDataSourceConnection.

    Theoretically, in some race condition, we could connect twice and then discard one connection <shrug>.
    ensureConnection will never return the discarded connection, though.

    (I think I got that right with respect to http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html)

    This keeps it from locking on another condition while holding the mutex.
Comment 1 Commit Notification 2013-04-29 13:01:33 UTC
Lionel Elie Mamane committed a patch related to this issue.
It has been pushed to "master":

http://cgit.freedesktop.org/libreoffice/core/commit/?id=1981819e81c1ad51b607d6af19e4e3776a74c75b

fdo#63391 deadlock on opening .odb file that auto-connects to the database



The patch should be included in the daily builds available at
http://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
http://wiki.documentfoundation.org/Testing_Daily_Builds
Affected users are encouraged to test the fix and report feedback.