From 101eea01c778ad255d3c8467e06643b23ff6bd76 Mon Sep 17 00:00:00 2001 From: Luboš Luňák Date: Mon, 22 Apr 2019 21:23:44 +0200 Subject: test in a separate helper process if OpenCL crashes (tdf#112252) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some OpenCL implementations may be broken, e.g. pocl simply asserts and aborts if it can't find Clang. In order to protect against crashes caused by faulty OpenCL drivers, when testing OpenCL functionality on OpenCL setup change, first do a simple test in a separate helper. Change-Id: I1cf328e731c48f47745b27c7130e7521254209f5 Reviewed-on: https://gerrit.libreoffice.org/71080 Tested-by: Jenkins Reviewed-by: Luboš Luňák --- desktop/source/app/opencl.cxx | 61 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'desktop') diff --git a/desktop/source/app/opencl.cxx b/desktop/source/app/opencl.cxx index f62c93e32e1f..a728ba2b8b7d 100644 --- a/desktop/source/app/opencl.cxx +++ b/desktop/source/app/opencl.cxx @@ -38,6 +38,7 @@ #include #include +#include using namespace ::osl; using namespace ::com::sun::star::uno; @@ -47,6 +48,61 @@ namespace desktop { #if HAVE_FEATURE_OPENCL +static bool testOpenCLDriver() +{ + // A simple OpenCL test run in a separate process in order to test + // whether the driver crashes (asserts,etc.) when trying to use OpenCL. + SAL_INFO("opencl", "Starting CL driver test"); + + OUString testerURL("$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/opencltest"); + rtl::Bootstrap::expandMacros(testerURL); //TODO: detect failure + + OUString deviceName, platformName; + openclwrapper::getOpenCLDeviceName( deviceName, platformName ); + rtl_uString* args[] = { deviceName.pData, platformName.pData }; + sal_Int32 numArgs = 2; + + oslProcess process; + oslSecurity security = osl_getCurrentSecurity(); + oslProcessError error = osl_executeProcess(testerURL.pData, args, numArgs, + osl_Process_SEARCHPATH | osl_Process_HIDDEN, security, + nullptr, nullptr, 0, &process ); + osl_freeSecurityHandle( security ); + if( error != osl_Process_E_None ) + { + SAL_WARN( "opencl", "failed to start CL driver test: " << error ); + return false; + } + // If the driver takes more than 10 seconds, it's probably broken/useless. + TimeValue timeout( 10, 0 ); + error = osl_joinProcessWithTimeout( process, &timeout ); + if( error == osl_Process_E_None ) + { + oslProcessInfo info; + info.Size = sizeof( info ); + error = osl_getProcessInfo( process, osl_Process_EXITCODE, &info ); + if( error == osl_Process_E_None ) + { + if( info.Code == 0 ) + { + SAL_INFO( "opencl", "CL driver test passed" ); + osl_freeProcessHandle( process ); + return true; + } + else + { + SAL_WARN( "opencl", "CL driver test failed - disabling: " << info.Code ); + osl_freeProcessHandle( process ); + return false; + } + } + } + SAL_WARN( "opencl", "CL driver test did not finish - disabling: " << error ); + osl_terminateProcess( process ); + osl_freeProcessHandle( process ); + return false; +} + static bool testOpenCLCompute(const Reference< XDesktop2 > &xDesktop, const OUString &rURL) { bool bSuccess = false; @@ -178,7 +234,10 @@ void Desktop::CheckOpenCLCompute(const Reference< XDesktop2 > &xDesktop) xBatch->commit(); } - bool bSucceeded = testOpenCLCompute(xDesktop, aURL); + // Hopefully at least basic functionality always works and broken OpenCL implementations break + // only when they are used to compute something. If this assumptions turns out to be not true, + // the driver check needs to be moved sooner. + bool bSucceeded = testOpenCLDriver() && testOpenCLCompute(xDesktop, aURL); { // restore the minimum group size std::shared_ptr xBatch(comphelper::ConfigurationChanges::create()); -- cgit