[Libreoffice-commits] core.git: 2 commits - svtools/source ucb/source

Stephan Bergmann sbergman at redhat.com
Fri Mar 1 08:19:31 PST 2013


 svtools/source/control/inettbc.cxx           |  117 ++++++++++++++++++++--
 ucb/source/ucp/webdav-neon/webdavcontent.cxx |  142 ++++++++++++++-------------
 ucb/source/ucp/webdav-neon/webdavcontent.hxx |    7 -
 3 files changed, 188 insertions(+), 78 deletions(-)

New commits:
commit 5da10275a7475efdbfd9de14ea58cf8f4c6c1582
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Mar 1 17:09:45 2013 +0100

    Related rhbz#915743: Abort UCB call from SvtMatchContext_Impl::Stop
    
    ...as otherwise the SvtMatchContext_Impl thread can continue to run for
    arbitrarily long, and the other thread calling Stop() and join() will block.
    
    However, especially the WebDAV UCP does not properly support aborting commands,
    see 260afe56fd6b2f34de8290f3cdb7d1df5b88f8a8 " neon commands cannot be aborted",
    so this is not yet enough to actually fix rhbz#915743 "thread deadlock/slow
    join in insert->hyperlink in impress."
    
    Change-Id: I0da899f824763e1b3d19bb5b38d906feb690b623

diff --git a/svtools/source/control/inettbc.cxx b/svtools/source/control/inettbc.cxx
index dc43a3d..9791aa2 100644
--- a/svtools/source/control/inettbc.cxx
+++ b/svtools/source/control/inettbc.cxx
@@ -25,13 +25,16 @@
 #include <svtools/inettbc.hxx>
 #include <com/sun/star/uno/Any.hxx>
 #include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/beans/Property.hpp>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/sdbc/XResultSet.hpp>
 #include <com/sun/star/sdbc/XRow.hpp>
 #include <com/sun/star/task/XInteractionHandler.hpp>
 #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
+#include <com/sun/star/ucb/UniversalContentBroker.hpp>
 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
+#include <com/sun/star/ucb/XCommandProcessor2.hpp>
 #include <com/sun/star/ucb/XProgressHandler.hpp>
 #include <com/sun/star/ucb/XContentAccess.hpp>
 #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
@@ -98,10 +101,14 @@ class SvtMatchContext_Impl: public salhelper::Thread
     String                          aBaseURL;
     String                          aText;
     SvtURLBox*                      pBox;
-    sal_Bool                            bStop;
     sal_Bool                            bOnlyDirectories;
     sal_Bool                            bNoSelection;
 
+    osl::Mutex mutex_;
+    bool stopped_;
+    css::uno::Reference< css::ucb::XCommandProcessor > processor_;
+    sal_Int32 commandId_;
+
     DECL_STATIC_LINK(               SvtMatchContext_Impl, Select_Impl, void* );
 
     virtual                         ~SvtMatchContext_Impl();
@@ -129,9 +136,9 @@ SvtMatchContext_Impl::SvtMatchContext_Impl(
     , aBaseURL( pBoxP->aBaseURL )
     , aText( rText )
     , pBox( pBoxP )
-    , bStop( sal_False )
     , bOnlyDirectories( pBoxP->bOnlyDirectories )
     , bNoSelection( pBoxP->bNoSelection )
+    , stopped_(false)
 {
     aLink.CreateMutex();
 
@@ -173,7 +180,19 @@ void SvtMatchContext_Impl::FillPicklist(std::vector<rtl::OUString>& rPickList)
 
 void SvtMatchContext_Impl::Stop()
 {
-    bStop = sal_True;
+    css::uno::Reference< css::ucb::XCommandProcessor > proc;
+    sal_Int32 id;
+    {
+        osl::MutexGuard g(mutex_);
+        if (!stopped_) {
+            stopped_ = true;
+            proc = processor_;
+            id = commandId_;
+        }
+    }
+    if (proc.is()) {
+        proc->abort(id);
+    }
     terminate();
 }
 
@@ -193,10 +212,12 @@ void SvtMatchContext_Impl::execute( )
 IMPL_STATIC_LINK( SvtMatchContext_Impl, Select_Impl, void*, )
 {
     // avoid recursion through cancel button
-    if( pThis->bStop )
     {
-        // completions was stopped, no display
-        return 0;
+        osl::MutexGuard g(pThis->mutex_);
+        if (pThis->stopped_) {
+            // Completion was stopped, no display:
+            return 0;
+        }
     }
 
     SvtURLBox* pBox = pThis->pBox;
@@ -543,9 +564,13 @@ String SvtURLBox::ParseSmart( String aText, String aBaseURL, String aWorkDir )
 void SvtMatchContext_Impl::doExecute()
 {
     ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
-    if( bStop )
+    {
         // have we been stopped while we were waiting for the mutex?
-        return;
+        osl::MutexGuard g(mutex_);
+        if (stopped_) {
+            return;
+        }
+    }
 
     // Reset match lists
     aCompletions.clear();
@@ -587,7 +612,81 @@ void SvtMatchContext_Impl::doExecute()
                 if ( aMainURL.Len() )
                 {
                     // if text input is a directory, it must be part of the match list! Until then it is scanned
-                    if ( UCBContentHelper::IsFolder( aMainURL ) && aURLObject.hasFinalSlash() )
+                    bool folder = false;
+                    if (aURLObject.hasFinalSlash()) {
+                        try {
+                            css::uno::Reference< css::uno::XComponentContext >
+                                ctx(comphelper::getProcessComponentContext());
+                            css::uno::Reference<
+                                css::ucb::XUniversalContentBroker > ucb(
+                                    css::ucb::UniversalContentBroker::create(
+                                        ctx));
+                            css::uno::Sequence< css::beans::Property > prop(1);
+                            prop[0].Name = "IsFolder";
+                            prop[0].Handle = -1;
+                            prop[0].Type = cppu::UnoType< bool >::get();
+                            css::uno::Any res;
+                            css::uno::Reference< css::ucb::XCommandProcessor >
+                                proc(
+                                    ucb->queryContent(
+                                        ucb->createContentIdentifier(aMainURL)),
+                                    css::uno::UNO_QUERY_THROW);
+                            css::uno::Reference< css::ucb::XCommandProcessor2 >
+                                proc2(proc, css::uno::UNO_QUERY);
+                            sal_Int32 id = proc->createCommandIdentifier();
+                            try {
+                                {
+                                    osl::MutexGuard g(mutex_);
+                                    processor_ = proc;
+                                    commandId_ = id;
+                                }
+                                res = proc->execute(
+                                    css::ucb::Command(
+                                        "getPropertyValues", -1,
+                                        css::uno::makeAny(prop)),
+                                    id,
+                                    css::uno::Reference<
+                                        css::ucb::XCommandEnvironment >());
+                            } catch (...) {
+                                if (proc2.is()) {
+                                    try {
+                                        proc2->releaseCommandIdentifier(id);
+                                    } catch (css::uno::RuntimeException & e) {
+                                        SAL_WARN(
+                                            "svtools.control",
+                                            "ignoring UNO RuntimeException "
+                                            << e.Message);
+                                    }
+                                }
+                                throw;
+                            }
+                            if (proc2.is()) {
+                                proc2->releaseCommandIdentifier(id);
+                            }
+                            {
+                                osl::MutexGuard g(mutex_);
+                                processor_.clear();
+                                // At least the neon-based WebDAV UCP does not
+                                // properly support aborting commands, so return
+                                // anyway now if an abort request had been
+                                // ignored and the command execution only
+                                // returned "successfully" after some timeout:
+                                if (stopped_) {
+                                    return;
+                                }
+                            }
+                            css::uno::Reference< css::sdbc::XRow > row(
+                                res, css::uno::UNO_QUERY_THROW);
+                            folder = row->getBoolean(1) && !row->wasNull();
+                        } catch (css::uno::Exception & e) {
+                            SAL_WARN(
+                                "svtools.control",
+                                "ignoring UNO Exception " << typeid(*&e).name()
+                                << ": " << e.Message);
+                            return;
+                        }
+                    }
+                    if ( folder )
                             Insert( aText, aMatch );
                     else
                         // otherwise the parent folder will be taken
commit 0c3500115c4fd86284a027fc32be704afcf77061
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Mar 1 16:50:18 2013 +0100

    Related rhbz#915743: Do not call into DAVResourceAccess with mutex locked
    
    ...from webdav Content::getResourceType, as otherwise Content::abort would be
    blocked waiting for the mutex (in code that would call abort, which will be
    required to fix rhbz#915743 "thread deadlock/slow join in insert->hyperlink in
    impress").  This required to get the odd reference to enum return type of
    getResourceType straight.
    
    Also, propagate information about !shouldAccessNetworkAfterException from
    getResourceType out to getPropertyValues, to avoid further calls that would
    again block/fail.
    
    Change-Id: I8b9d43a61eb4078acb90079c4eb7aa98a59a8983

diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.cxx b/ucb/source/ucp/webdav-neon/webdavcontent.cxx
index 5c2aa05..2901b84 100644
--- a/ucb/source/ucp/webdav-neon/webdavcontent.cxx
+++ b/ucb/source/ucp/webdav-neon/webdavcontent.cxx
@@ -782,8 +782,8 @@ void SAL_CALL Content::addProperty( const rtl::OUString& Name,
             {
                 try
                 {
-                    const ResourceType & rType = getResourceType( xEnv );
-                    switch ( rType )
+                    ResourceType eType = getResourceType( xEnv );
+                    switch ( eType )
                     {
                     case UNKNOWN:
                     case DAV:
@@ -877,8 +877,8 @@ void SAL_CALL Content::removeProperty( const rtl::OUString& Name )
             {
                 try
                 {
-                    const ResourceType & rType = getResourceType( xEnv );
-                    switch ( rType )
+                    ResourceType eType = getResourceType( xEnv );
+                    switch ( eType )
                     {
                         case UNKNOWN:
                         case DAV:
@@ -1175,11 +1175,11 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues(
         /////////////////////////////////////////////////////////////////////
 
         // First, identify whether resource is DAV or not
-        const ResourceType & rType = getResourceType( xEnv, xResAccess );
-
         bool bNetworkAccessAllowed = true;
+        ResourceType eType = getResourceType(
+            xEnv, xResAccess, &bNetworkAccessAllowed );
 
-        if ( DAV == rType )
+        if ( eType == DAV )
         {
             // cache lookup... getResourceType may fill the props cache via
             // PROPFIND!
@@ -1269,8 +1269,8 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues(
                     }
                     catch ( DAVException const & e )
                     {
-                        bNetworkAccessAllowed
-                            = shouldAccessNetworkAfterException( e );
+                        bNetworkAccessAllowed = bNetworkAccessAllowed
+                            && shouldAccessNetworkAfterException( e );
 
                         if ( !bNetworkAccessAllowed )
                         {
@@ -1341,7 +1341,7 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues(
         NeonUri aUri( xResAccess->getURL() );
         aUnescapedTitle = aUri.GetPathBaseNameUnescaped();
 
-        if ( rType == UNKNOWN )
+        if ( eType == UNKNOWN )
         {
             xProps.reset( new ContentProperties( aUnescapedTitle ) );
         }
@@ -1349,7 +1349,7 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues(
         // For DAV resources we only know the Title, for non-DAV
         // resources we additionally know that it is a document.
 
-        if ( rType == DAV )
+        if ( eType == DAV )
         {
             //xProps.reset(
             //    new ContentProperties( aUnescapedTitle ) );
@@ -3070,83 +3070,93 @@ Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess )
 }
 
 //=========================================================================
-const Content::ResourceType & Content::getResourceType(
+Content::ResourceType Content::getResourceType(
                     const uno::Reference< ucb::XCommandEnvironment >& xEnv,
-                    const std::auto_ptr< DAVResourceAccess > & rResAccess )
+                    const std::auto_ptr< DAVResourceAccess > & rResAccess,
+                    bool * networkAccessAllowed)
     throw ( uno::Exception )
 {
-    if ( m_eResourceType == UNKNOWN )
     {
-        osl::Guard< osl::Mutex > aGuard( m_aMutex );
+        osl::MutexGuard g(m_aMutex);
+        if (m_eResourceType != UNKNOWN) {
+            return m_eResourceType;
+        }
+    }
 
-        ResourceType eResourceType;
-        eResourceType = m_eResourceType;
+    ResourceType eResourceType;
 
-        const rtl::OUString & rURL = rResAccess->getURL();
-        const rtl::OUString aScheme(
-            rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() );
+    const rtl::OUString & rURL = rResAccess->getURL();
+    const rtl::OUString aScheme(
+        rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() );
 
-        if ( aScheme == FTP_URL_SCHEME )
+    if ( aScheme == FTP_URL_SCHEME )
+    {
+        eResourceType = FTP;
+    }
+    else
+    {
+        try
         {
-            eResourceType = FTP;
+            // Try to fetch some frequently used property value, e.g. those
+            // used when loading documents... along with identifying whether
+            // this is a DAV resource.
+            std::vector< DAVResource > resources;
+            std::vector< rtl::OUString > aPropNames;
+            uno::Sequence< beans::Property > aProperties( 5 );
+            aProperties[ 0 ].Name = rtl::OUString("IsFolder");
+            aProperties[ 1 ].Name = rtl::OUString("IsDocument");
+            aProperties[ 2 ].Name = rtl::OUString("IsReadOnly");
+            aProperties[ 3 ].Name = rtl::OUString("MediaType");
+            aProperties[ 4 ].Name = DAVProperties::SUPPORTEDLOCK;
+
+            ContentProperties::UCBNamesToDAVNames( aProperties, aPropNames );
+
+            rResAccess->PROPFIND( DAVZERO, aPropNames, resources, xEnv );
+
+            if ( resources.size() == 1 )
+            {
+                osl::MutexGuard g(m_aMutex);
+                m_xCachedProps.reset(
+                    new CachableContentProperties( resources[ 0 ] ) );
+                m_xCachedProps->containsAllNames(
+                    aProperties, m_aFailedPropNames );
+            }
+
+            eResourceType = DAV;
         }
-        else
+        catch ( DAVException const & e )
         {
-            try
-            {
-                // Try to fetch some frequently used property value, e.g. those
-                // used when loading documents... along with identifying whether
-                // this is a DAV resource.
-                std::vector< DAVResource > resources;
-                std::vector< rtl::OUString > aPropNames;
-                uno::Sequence< beans::Property > aProperties( 5 );
-                aProperties[ 0 ].Name
-                    = rtl::OUString("IsFolder");
-                aProperties[ 1 ].Name
-                    = rtl::OUString("IsDocument");
-                aProperties[ 2 ].Name
-                    = rtl::OUString("IsReadOnly");
-                aProperties[ 3 ].Name
-                    = rtl::OUString("MediaType");
-                aProperties[ 4 ].Name
-                    = DAVProperties::SUPPORTEDLOCK;
-
-                ContentProperties::UCBNamesToDAVNames(
-                    aProperties, aPropNames );
-
-                rResAccess->PROPFIND(
-                    DAVZERO, aPropNames, resources, xEnv );
-
-                if ( resources.size() == 1 )
-                {
-                    m_xCachedProps.reset(
-                        new CachableContentProperties( resources[ 0 ] ) );
-                    m_xCachedProps->containsAllNames(
-                        aProperties, m_aFailedPropNames );
-                }
+            rResAccess->resetUri();
 
-                eResourceType = DAV;
+            if ( e.getStatus() == SC_METHOD_NOT_ALLOWED )
+            {
+                // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
+                // resource is NON_DAV
+                eResourceType = NON_DAV;
             }
-            catch ( DAVException const & e )
+            else if (networkAccessAllowed != 0)
             {
-                rResAccess->resetUri();
-
-                if ( e.getStatus() == SC_METHOD_NOT_ALLOWED )
-                {
-                    // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
-                    // resource is NON_DAV
-                    eResourceType = NON_DAV;
-                }
+                *networkAccessAllowed = *networkAccessAllowed
+                    && shouldAccessNetworkAfterException(e);
             }
         }
+    }
+
+    osl::MutexGuard g(m_aMutex);
+    if (m_eResourceType == UNKNOWN) {
         m_eResourceType = eResourceType;
+    } else {
+        SAL_WARN_IF(
+            eResourceType != m_eResourceType, "ucb.ucp.webdav",
+            "different resource types for <" << rURL << ">: "
+            << +eResourceType << " vs. " << +m_eResourceType);
     }
     return m_eResourceType;
 }
 SAL_WNODEPRECATED_DECLARATIONS_POP
 
 //=========================================================================
-const Content::ResourceType & Content::getResourceType(
+Content::ResourceType Content::getResourceType(
                     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
     throw ( uno::Exception )
 {
diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.hxx b/ucb/source/ucp/webdav-neon/webdavcontent.hxx
index 637ab7f..83afb3f 100644
--- a/ucb/source/ucp/webdav-neon/webdavcontent.hxx
+++ b/ucb/source/ucp/webdav-neon/webdavcontent.hxx
@@ -133,16 +133,17 @@ private:
     getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess );
     SAL_WNODEPRECATED_DECLARATIONS_POP
 
-    const ResourceType &
+    ResourceType
     getResourceType( const ::com::sun::star::uno::Reference<
                          ::com::sun::star::ucb::XCommandEnvironment >& xEnv )
         throw ( ::com::sun::star::uno::Exception );
 
     SAL_WNODEPRECATED_DECLARATIONS_PUSH
-    const ResourceType &
+    ResourceType
     getResourceType( const ::com::sun::star::uno::Reference<
                           ::com::sun::star::ucb::XCommandEnvironment >& xEnv,
-                     const std::auto_ptr< DAVResourceAccess > & rResAccess )
+                     const std::auto_ptr< DAVResourceAccess > & rResAccess,
+                     bool * networkAccessAllowed = 0)
         throw ( ::com::sun::star::uno::Exception );
     SAL_WNODEPRECATED_DECLARATIONS_POP
 


More information about the Libreoffice-commits mailing list